Skip to main content

Telnyx Storage: CloudFS (Beta) — Full Documentation

Complete page content for CloudFS (Beta) (Storage section) of the Telnyx developer docs (https://developers.telnyx.com). This file: https://developers.telnyx.com/development/llms/storage-cloudfs-beta-llms-full-txt.md · Root index: https://developers.telnyx.com/llms.txt

Get Started

CloudFS

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs.md
CloudFS is a POSIX filesystem you mount on any host or container. Once mounted, it behaves like a local directory — read, write, mkdir, rename, git init — but every byte is stored durably in Telnyx Cloud Storage, and the same filesystem can be mounted by many clients at once — a fleet of agents reading and writing it concurrently. You mount it with the open-source JuiceFS Community Edition client (Apache-2.0), which you run yourself — Telnyx does not host or bundle it. JuiceFS has no server process: the client does all the filesystem work and talks directly to a metadata database and to object storage, so no JuiceFS component runs on the Telnyx side. Telnyx provides and authenticates the two managed backends — the metadata database and object storage — and hands you a ready-to-mount filesystem. The target use case is a shared, persistent filesystem for AI agents: provision one CloudFS, mount it once, and every file, repo, and checkpoint an agent produces is there — and still there on the next mount, from anywhere. Do not touch the cloudfs-fs-* bucket directly. A CloudFS filesystem’s data lives in a bucket named cloudfs-fs-<hex> inside your own Telnyx Cloud Storage account — it appears alongside your other buckets and is reachable with your API key. Its objects are opaque JuiceFS blocks (chunks/… plus internal bookkeeping), not your files. Deleting, renaming, or editing objects in that bucket out of band corrupts the filesystem — a missing block is unrecoverable and there is no repair path. Manage a CloudFS filesystem only through the CloudFS API and a JuiceFS mount; treat its bucket as internal, hands-off storage. CloudFS is in beta. The API surface and behavior may still change as it moves toward general availability.

Next Steps


Quick Start

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/quickstart.md
Get up and running with CloudFS: create a filesystem over the API, then mount it with the JuiceFS client inside a Linux container and use it like any local directory — write files, read them back, run git. The whole path below is verified end-to-end against production. CloudFS is built on JuiceFS Community Edition (see How CloudFS Works for the architecture). There is no server process to run: the JuiceFS client on your host talks directly to a per-filesystem metadata database and to Telnyx Cloud Storage. That means you hold two credentials — the meta_token (returned on create) and your TELNYX_API_KEY — and the client does the rest.

1. Create a Filesystem

POST /v2/storage/cloudfs. The Idempotency-Key header is required (a request without it is rejected with 400), and so is region — there is no default. Allowed regions are us-central-1, us-east-1, and us-west-1.
Replaying the same Idempotency-Key returns the same filesystem instead of creating a second one. A 201 response looks like this:
This is the only time you see the token. meta_url (with the token inline as the password) and the standalone meta_token are returned only on create and on rotate. GET /v2/storage/cloudfs/{id} returns meta_url without the token and no meta_token at all — it cannot be read back. Store the token securely now; if you lose it, rotate to get a new one. You’ll use two values from this response to mount:
  • meta_url — the full connection string, token included. This is the metadata endpoint; the host is always us-east-1.telnyxcloudfs.com regardless of the filesystem’s region.
  • id — the filesystem UUID, for later API calls (detail, rename, rotate).
The response’s s3_bucket (cloudfs-fs-<hex>) is in your Telnyx Cloud Storage account, but it holds CloudFS’s internal blocks — not your files. Never modify or delete its objects directly; that corrupts the filesystem. Read and write only through the mount below. See How CloudFS Works.

2. Mount It with JuiceFS

CloudFS pre-formats the volume during provisioning — the bucket already contains the JuiceFS volume metadata. Do not run juicefs format. The filesystem is already formatted; running format against it fails with cannot update volume name. Go straight to juicefs mount. (The one exception: if the filesystem’s status is needs_format, it does need a one-time juicefs format before mounting — see Mounting.) Mount inside a Linux container with FUSE — a portable path that runs the same anywhere and needs no FUSE install on the host. (You can also mount natively on any Linux or macOS host that has FUSE/macFUSE installed.) The data lane authenticates to Telnyx Cloud Storage over S3: your TELNYX_API_KEY is the access key, and the secret key can be any non-empty placeholder (Telnyx Storage ignores the SigV4 signature, but JuiceFS’s AWS SDK rejects an empty secret). See Cloud Storage authentication for why the secret is ignored.
Check /tmp/juicefs.log for progress. Once mounted, df -h /mnt/agentfs shows the volume.

3. Smoke-Test Over POSIX

The mount is a normal directory. Write a file, read it back, and initialize a git repo — all standard POSIX, no CloudFS-specific calls.
Data written here lands in Telnyx Cloud Storage as 4 MiB block objects under chunks/… in the filesystem’s bucket, and persists across unmount and remount — remount with the same meta_url and your files are still there.

Next Steps

  • How CloudFS Works — the metadata and data lanes, the two credentials, and the on-disk layout
  • Mounting — the mount recipe in depth, FUSE requirements, and remount
  • API Reference — the full endpoint surface, including rotate and delete
  • Overview — what CloudFS is and when to use it

Concepts

Filesystems From First Principles

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/concepts/filesystems-from-first-principles.md
CloudFS gives you a POSIX filesystem you mount on any host or container, backed by Telnyx Cloud Storage. To understand how it works — and why it is shaped the way it is — these Concepts pages build the idea from the bottom up:
  1. What a filesystem is and how a local one is built (this page)
  2. Why past network filesystems fall short, and how the early cluster filesystems reframed storage (NFS and AFS → GFS, HDFS, MooseFS)
  3. How CloudFS puts it together
The framing follows the standard treatment in Operating Systems: Three Easy Pieces (OSTEP), by Remzi and Andrea Arpaci-Dusseau. It is worth reading in full; these pages borrow just enough to motivate the design.

What a Filesystem Actually Is

Strip away the tooling and a filesystem is two abstractions:
  • A file is a linear array of bytes with a low-level name — a number, the inode number. The operating system does not care whether those bytes are a JPEG or C source; it stores them and hands them back intact.
  • A directory is itself a file, but its contents are specific: a list of (human-readable name → inode number) pairs. Nest directories inside directories and you get the tree you navigate every day.
So underneath a familiar path like /home/agent/work.log, a filesystem is really two things: an index that maps names to inodes and inodes to the location of bytes, and the bytes themselves. Everything else — open/read/write/close, permissions, hard and symbolic links — is built on top of those two.

How a Local Filesystem Is Built

On a single disk, those two things live in two different places. OSTEP’s teaching filesystem, vsfs, divides the disk into an inode table plus small bitmaps that track which inodes and blocks are free — this is the metadata index — and a much larger data region of fixed-size blocks that holds file contents. Each inode is a compact record of metadata (permissions, timestamps, size) plus a multi-level index of pointers to the file’s data blocks. Reading a file means reading its inode to find the block pointers, then reading the blocks; writing a file may also flip an allocation bit and rewrite the inode. The Fast File System added the lesson that where you place those blocks matters: the original Unix filesystem treated the disk like RAM and paid for it in seeks, so FFS made the filesystem “disk-aware” — keep an inode near its data, keep files of one directory together, respect the physical medium. The durable takeaway is this: a filesystem is a metadata index over a pile of data blocks — two kinds of state with two very different access patterns. Metadata is small, hot, and demands consistency: an inode is either allocated or it is not. Data is large and wants throughput. Hold onto that split; it is the key to everything that follows.

Staying Consistent Across Crashes

The metadata index has one more demand: it must survive a crash. A single logical operation — appending a block to a file, say — touches several structures (the allocation bitmap, the inode, the data block), but the disk writes them one at a time. Lose power in between and the index is left inconsistent: a block marked used by no file, or an inode pointing at garbage. Early filesystems repaired this after the fact with fsck, scanning the whole disk on reboot — which stops scaling as disks grow. The durable fix, journaling (write-ahead logging), is borrowed straight from databases: write your intended changes to a log and commit them there first, then apply them to their real homes; after a crash, replay the committed log. Recovery then costs the size of the log, not the size of the disk. Keep this one in mind — it is the cleanest argument for where CloudFS keeps its metadata. And the medium underneath can lie: a sector rots, or silently returns the wrong bytes. Filesystems and storage layers defend against it with checksums and scrubbing; CloudFS leaves that to the object store, which does it for you.

Further Reading

Next: Network Filesystems — what happens when you stretch this across a network.

Network Filesystems

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/concepts/network-filesystems.md
A local filesystem is a metadata index over a pile of data blocks. To share one between machines you must move one or both of those halves across a network — and decades of distributed filesystems show that is where the difficulty lives.

NFS: Stateless, and Brittle Over the WAN

Sun’s Network File System makes the filesystem a client/server protocol. Its central design goal is simple, fast crash recovery, achieved by making the server stateless — it keeps no per-client state, so every request carries everything needed to service it (a READ sends the explicit offset; the client, not the server, tracks position). Most operations are idempotent, so the failure handler collapses to a single rule: set a timer, and if no reply arrives, retry. Elegant — but it has costs that bite hard over a wide-area network:
  • Weak cache consistency. Clients cache and buffer writes for performance, which introduces the update-visibility problem. NFS papers over it with flush-on-close and an attribute cache with a timeout (~3 seconds), so whether a client sees the latest version of a file “depends on whether the cache entry has timed out” — the source of NFS’s notorious occasional stale reads.
  • The hang. Because the client simply retries until the server answers, an unresponsive or partitioned server makes the client block indefinitely. A read() that never returns takes the calling process — and often a whole pipeline — down with it. A network partition is indistinguishable from a crash.
  • Small files are easy; large files are not. Over a LAN with small files NFS is fine. Over a WAN, file seeks and mid-file updates on large files get ugly, and rapid writes suffer under lost packets.
Put it concretely with a plain client/server mount. The server exports a directory; a client mounts it and it looks local:
With a default hard mount, if fileserver crashes or the network partitions, any process that so much as stats a path under /mnt/shared blocks in uninterruptible sleep — ls /mnt/shared hangs, shrugs off Ctrl-C, and the console fills with NFS server fileserver not responding, still trying. The mount doesn’t return an error; it waits, and takes the caller down with it. That is tolerable on a quiet LAN with a reliable server; for agents scattered across the internet — where partitions are routine and every mount is one flaky link from a hung process — it is the wrong default.

AFS: Whole-File Caching, and Stateful Bookkeeping

The Andrew File System was built for scale. On open() it fetches the whole file to the client’s local disk and serves subsequent reads and writes locally; on close() it ships the whole file back. To avoid clients constantly polling “has this changed?”, AFS added callbacks — a promise from the server to notify a client when a cached file changes — giving close-to-open consistency. It scales better than NFS, but the design fights our use case:
  • Callback state is awkward for clients that come and go. A client that was offline may have missed an invalidation and must revalidate its whole cache on return; a rebooted server does not know which clients cache what and must have everyone re-validate. Ephemeral agents — containers that appear, work, and vanish — are exactly the clients this bookkeeping handles worst.
  • Whole-file caching punishes the workload we care about. Fetching and rewriting an entire file just to append one line to a shared worklog, or to touch a small region of a large file, is precisely what AFS does poorly. AFS itself notes that its baseline consistency is not enough for concurrent updates to something like a shared code repository — you still need explicit file-level locking.
The through-line: NFS and AFS both begin with a filesystem that assumes one server owns the disk, and then bolt a network onto it. For a fleet of ephemeral agents working on a shared tree, over the public internet, on top of object storage rather than a local disk, that is the wrong starting shape.

Separating Metadata From Data

By the early 2000s a different design had emerged — built for a fleet of cheap, failure-prone machines from the start, rather than making a single server’s disk look remote.

Google File System

Google File System (GFS, 2003) split the problem cleanly in two:
  • a single master holds all the metadata — the namespace and the map from each file to its chunks — in memory, and
  • a fleet of chunkservers holds the file data as large chunks (64 MB), replicated for durability.
The move that matters: the master is kept out of the data path. A client asks the master where a file’s chunks live, then streams the bytes directly to and from the chunkservers. Metadata (small, hot, consistency-critical) and data (large, bulk) are served by different systems on different paths — the same split we saw inside the local filesystem, now drawn across a cluster.

HDFS and MooseFS

HDFS is the open-source realization of that design: a NameNode holds the namespace and the file→block map — “user data never flows through the NameNode” — while DataNodes store the blocks (128 MB) and serve reads and writes directly to clients. MooseFS applied the same master-plus-chunkservers split but exposed a full POSIX filesystem you mount, closing the gap back to the local-filesystem interface. These systems fixed what NFS and AFS could not: they stopped pretending one server owns a disk, and instead let an authoritative metadata service coordinate a scalable pool of data storage. What they still asked of you was to run that metadata master and that fleet of data servers yourself — which is exactly the operational burden CloudFS removes.

Further Reading

Next: How CloudFS Works — JuiceFS takes this split to its cloud conclusion.

How CloudFS Works

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/concepts/how-cloudfs-works.md
This page is the destination of a short arc. If you want the reasoning behind the design, read the background first:
  1. Filesystems From First Principles — a filesystem is a metadata index over a pile of data blocks.
  2. Network Filesystems — why bolting a network onto a disk-owning server is brittle, and how GFS, HDFS, and MooseFS split an authoritative metadata service from a scalable pool of data storage.
CloudFS is where that arc lands: a POSIX filesystem you mount on any host or container, backed by Telnyx Cloud Storage.

How CloudFS Does It

CloudFS is built on JuiceFS, which — in its authors’ words — was “inspired by Google File System, HDFS and MooseFS.” JuiceFS takes the metadata/data split those systems proved at cluster scale and replaces each half with a managed cloud primitive, so you operate neither a metadata master nor a fleet of data servers:
  • The metadata index — the master’s job in GFS, the NameNode’s in HDFS — becomes a transactional database. The database provides strong consistency for the small, hot, correctness-critical half: an entry is committed or it is not, and every client reads the same tree. This is the direct answer to NFS’s stale-attribute cache and AFS’s callback bookkeeping — put the index in one consistent place that all clients share, rather than caching copies and trying to keep them in sync. It also inherits the database’s transactions: the crash-consistency machinery a local filesystem hand-builds as journaling — write-ahead log, commit, replay — is simply what the database already does, so a metadata change is one atomic transaction with no partial-update window and no fsck-style recovery scan.
  • The data blocks — the chunkservers’ job — become object storage (Telnyx Cloud Storage). JuiceFS splits every file into a chunk → slice → block hierarchy and writes the blocks as ordinary objects; object storage supplies the durability and throughput for the large half. The blocks are opaque — you cannot reassemble a file from the bucket alone, because the index that orders them lives in the metadata database. Object storage also rewards writing new immutable objects over rewriting in place, so JuiceFS follows a log-structured discipline: each write becomes a new slice, never an overwrite, and a background compaction later merges overlapping slices and reclaims the garbage — exactly the cleaner a log-structured filesystem runs.
  • There is no CloudFS server in the data path. JuiceFS is a “rich client”: like AFS’s client and MooseFS’s FUSE mount, all the filesystem logic — the directory tree, inode allocation, splitting files into blocks, caching — runs in the process that mounts the volume. But instead of caching whole files and chasing callbacks, it reads and writes the shared metadata database directly, so consistency comes from the database rather than from a promise a server has to remember. When you juicefs mount, the client opens one connection to the metadata database and one to object storage, and serves POSIX calls from those two.
CloudFS is Telnyx’s managed packaging of JuiceFS Community Edition (Apache-2.0): Telnyx runs and authenticates both the metadata database and the object storage and hands you a formatted, ready-to-mount filesystem. Because JuiceFS Community Edition is a client library with no server process, there is no JuiceFS component running on the Telnyx side at all. The server side is a generic managed metadata database and object storage; every line of filesystem logic runs in the open-source JuiceFS client you mount — which you can read, pin a version of, and run yourself. CloudFS is that community client plus managed backends and a control-plane API, not a proprietary server tier. For the storage format in depth, see JuiceFS’s own architecture documentation, including its how JuiceFS stores files section.

The Two Lanes

Concretely, a CloudFS mount talks to two backends over two independent lanes, each with its own credential. There is no CloudFS server in the request path — your client connects to both directly.

The Metadata Lane

The client reaches metadata over the connection string CloudFS gives you as meta_url:
A few things are load-bearing here:
  • You connect to a managed metadata endpoint, not to the database directly. The public host us-east-1.telnyxcloudfs.com:5432 is a pooled front end to a per-filesystem metadata database (fs_<hex>). The database server itself is not directly reachable.
  • TLS is required. The connection uses sslmode=require; there is no plaintext metadata path.
  • The meta_token is the password. In the meta_url above, the cloudfs_tok_... embedded before the @ is the meta_token used as the connection password. It is a managed, rotatable credential (see The Metadata Token Lifecycle) — not the underlying database’s own credential, which you never handle.
Metadata is centralized in us-east-1 for every filesystem, no matter which data region you pick. A us-central-1 or us-west-1 filesystem still has its metadata host set to us-east-1.telnyxcloudfs.com. Always use the host embedded in meta_url. Because metadata lives only in us-east-1, a client mounting from another region pays a network round-trip on every metadata operation, so metadata-heavy work (listing large trees, many small files) is slower the farther you mount from us-east-1. Data throughput is unaffected — that lane goes to your region’s storage endpoint.

The Data Lane

File contents go to a per-filesystem bucket named cloudfs-fs-<hex> on Telnyx Cloud Storage, reached through the S3 endpoint for the filesystem’s region (s3_endpoint, e.g. https://us-east-1.telnyxcloudstorage.com). JuiceFS splits every file into 4 MiB block objects and writes them under chunks/… in that bucket; a 10 MiB file plus a small git repo, for example, lands as dozens of block objects. The blocks are opaque to S3 — reconstructing a file requires the chunk/slice index from the metadata lane. That bucket lives in your own Telnyx Cloud Storage account — it shows up in your bucket list and is reachable with your TELNYX_API_KEY, exactly like any other bucket you own. But its contents are CloudFS’s internal state, not your files: the chunks/… objects are opaque 4 MiB JuiceFS blocks, and a small juicefs_uuid object holds the volume format. Do not delete, rename, move, or edit objects in a cloudfs-fs-* bucket by hand. An out-of-band change corrupts the filesystem — a missing or altered block cannot be reconstructed, and there is no fsck to repair it. Read and write your files through the mount, and leave the bucket to JuiceFS. Authentication to the data lane reuses your account credentials, following the Telnyx Cloud Storage model:
  • The S3 access-key is your TELNYX_API_KEY.
  • The S3 secret-key is ignored — Telnyx Storage does not verify the SigV4 signature (see Cloud Storage authentication). You must still supply some non-empty secret, because JuiceFS’s AWS SDK rejects empty static credentials.
CloudFS pre-formats the bucket at create time: provisioning writes a juicefs_uuid object and formats the volume (JuiceFS volume name cloudfs-fs-<hex>). Do not run juicefs format against a ready filesystem — it is already formatted, and re-formatting fails with cannot update volume name. Just mount. The one exception is a filesystem whose status is needs_format, which was provisioned without the final format step: format it once as described in Mounting, then mount.

Two Credentials, One API Key

Putting the lanes together, a mounting client holds exactly what it needs and nothing more: The point of splitting the credentials this way is that the client never holds a raw database credential. It talks to the metadata endpoint with a managed meta_token that Telnyx can rotate independently of the underlying metadata database, and it never connects to the database server directly. Your API key, meanwhile, only ever reaches object storage. Compromising a mount host exposes a rotatable metadata token and your (already-scoped) API key — not standing database credentials. Create and rotate are the only responses that return the meta_token (and the token-bearing meta_url). GET detail returns meta_url without the token, and list returns neither. Store the token when you create the filesystem — there is no way to read it back.

Regions

You choose a data region at create time: us-central-1, us-east-1, or us-west-1. That region is required — there is no default — and it determines the S3 endpoint (s3_endpoint) and where the file blocks physically live. It is the only region choice you make. Metadata is always in us-east-1. Picking us-west-1 for data does not move the metadata database; that filesystem’s metadata host is still us-east-1.telnyxcloudfs.com. Mount as close to us-east-1 as your data region allows if metadata latency matters to your workload.

The Metadata Token Lifecycle

The meta_token is the one credential in the system designed to be rolled. Rotation is a control-plane action: POST /v2/storage/cloudfs/{id}/actions/rotate-meta-token (Idempotency-Key required) issues a new meta_token and returns a new token-bearing meta_url. Rotation touches only the token — the metadata database and the S3 bucket are unchanged, so no data moves and no files are re-encrypted or re-keyed. The cutover is connection-scoped, which makes rotation safe to run against a live filesystem:
  • The old token stops authenticating on the next metadata connection — any new juicefs mount (or reconnect) must use the new meta_url.
  • An already-mounted client is unaffected on its existing connection. It keeps working with the connection it opened before rotation; you only need the new token the next time it reconnects.
So the operational rule is: rotate, then update wherever the old meta_url is stored (secrets, deploy config) before your mounts next reconnect.

Filesystem Status

Each filesystem carries a status: The steady states are ready, needs_format, and failed; provisioning and deleting are transitional. There is no soft-delete or trash lifecycle — deleted is terminal and permanent.

Further Reading

Next Steps


Guides

Mounting a Filesystem

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/mount.md
A CloudFS filesystem is mounted with the JuiceFS Community Edition client: give it the metadata URL and S3 credentials below, and it exposes a POSIX filesystem at a mountpoint through FUSE. This page is the end-to-end mount recipe for each environment, verified against a live filesystem. If your host can’t do FUSE at all, serve the filesystem over WebDAV instead — no kernel support needed. If you haven’t created a filesystem yet, start with the Quick Start. For the two-lane architecture behind the credentials, see How CloudFS Works.

Prerequisites

  • The JuiceFS Community Edition client. Install it per the JuiceFS docs. This page was verified end-to-end with JuiceFS CE 1.4.0.
  • An existing CloudFS filesystem (create one), and the meta_url and meta_token from its create response. The token is returned only at create (and on rotate) — if you didn’t store it, you cannot reconstruct it and must rotate to get a new one.
  • FUSE. A usable /dev/fuse on Linux, or macFUSE on macOS. (Serving Without FUSE needs neither.)

Credentials the Client Needs

The client holds three things. None of them is a raw database password — the metadata token is the password, embedded in the URL. The meta_url returned by create already has the token inline as the password:
The meta_url returned by GET /v2/storage/cloudfs/{id} is the same string without the token:
If you’re working from the tokenless URL, splice your stored meta_token in as the password (postgres://fs_<hex>:<meta_token>@...). The host is always the region metadata host us-east-1.telnyxcloudfs.com — metadata is centralized there regardless of the filesystem’s data region.

Set the Environment

CloudFS volumes are formatted without embedded object-storage credentials, so JuiceFS picks them up from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY at mount time. Set them explicitly. Telnyx Cloud Storage authenticates on the access key alone and ignores the SigV4 signature, so the secret can be any non-empty string — see Cloud Storage authentication. An empty secret fails: JuiceFS’s AWS SDK rejects it with static credentials are empty. The same environment also feeds Serving Without FUSE. Do not run juicefs format against a filesystem whose status is ready. Provisioning already formats the volume (the bucket ships with a juicefs_uuid object and a fixed volume name), and re-formatting fails with cannot update volume name. The one exception is a filesystem in needs_format — see Formatting a needs_format filesystem.

Mount with FUSE

The first positional argument is the metadata URL; the second is the mountpoint. Mount in the background and write logs to a file so the mount doesn’t block your terminal — on success the command returns immediately and the filesystem is live at the mountpoint. Needs a usable /dev/fuse, which stock kernels have.
Watch /tmp/juicefs.log for the mount status and any warnings. The most portable way to mount — no FUSE install on the host, identical behavior everywhere. The container needs FUSE and the juicefs binary: run it privileged and pass the FUSE device through with --device /dev/fuse.
Inside the container, install the client and mount:
--privileged and --device /dev/fuse are what let FUSE mount inside the container. Without them the mount fails to open /dev/fuse. If you bake the juicefs binary and fuse into your own image, you can skip the install step and go straight to juicefs mount. With macFUSE installed and its system extension approved, the recipe is the same — pick a mountpoint in your home directory:
On a managed Mac, MDM policy often blocks macFUSE’s system extension from loading at all. You don’t need it: the WebDAV serve path ends in a real Finder-mounted volume using only what ships with macOS. The --no-usage-report flag opts out of JuiceFS’s anonymous usage reporting. By default the JuiceFS client reports core metrics (such as its version) to the JuiceFS project on mount; it does not include user data. These docs pass --no-usage-report on every mount so CloudFS filesystems don’t phone home by default — drop the flag if you’d like to share usage data with the upstream project.

Formatting a needs_format Filesystem

If GET /v2/storage/cloudfs/{id} reports "status": "needs_format", the bucket and metadata database exist but the volume was never formatted, and mounting fails with database is not formatted, please run juicefs format ... first. This is the one case where you run juicefs format — once, then mount as normal:
<s3_endpoint> and <s3_bucket> come from the filesystem’s detail response, and the JuiceFS volume name must be the s3_bucket value (cloudfs-fs-<hex>) — any other name is rejected. Keep AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY exported (format probes the bucket over S3) and leave --access-key / --secret-key unset: the stored volume config then carries no credentials, same as a factory-formatted filesystem. Note that --no-usage-report is a mount flag — format doesn’t accept it.

Verify the Mount

The checks below are written for Linux with the /mnt/agentfs mountpoint. On macOS, substitute yours (e.g. ~/agentfs), check with mount | grep agentfs in place of mountpoint, and hash with md5 in place of md5sum.
Anything you write is chunked into 4 MiB block objects in the filesystem’s Cloud Storage bucket and persists across unmount/remount. A normal filesystem workflow works on top of it — for example git init and git commit inside the mountpoint behave as expected.

Unmount

Unmounting only tears down the local FUSE mount; it does not touch the metadata database or the bucket. Remounting the same META_URL brings all files back.

Troubleshooting

Next Steps

  • Serving Without FUSE — serve the filesystem over WebDAV on hosts that can’t mount
  • Concurrent Access — mount the same filesystem from many clients at once, and coordinate writers with locks
  • How CloudFS Works — the metadata and data lanes, and what lives where
  • API Reference — create, list, get, update, delete, and rotate the metadata token
  • Overview — what CloudFS is and when to reach for it

Serving Without FUSE

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/serve.md
A WebDAV-served filesystem is not full POSIX. Everyday file operations work, but the POSIX surface a FUSE mount provides does not survive the HTTP hop. Good for: reading and writing files, shuttling them between machines, browsing in Finder, everyday ls / cd / cp / mv / mkdir, and any app that speaks WebDAV directly. No good for: git working trees (git init fails), executing binaries in place (noexec), coordinating writers with file locks (flock is local-only), or anything that needs faithful permissions and ownership. For those, mount with FUSE. Mounting a filesystem goes through FUSE, and not every host has FUSE to give: a managed Mac whose MDM policy blocks macFUSE, a container you can’t run with --device /dev/fuse, a host where you aren’t root. The same JuiceFS client can serve the filesystem instead: juicefs webdav is an ordinary user-space process listening on a TCP port — it holds the same two backend connections a mount holds and exposes the filesystem as a WebDAV endpoint over HTTP, with no kernel support at all. Serving is not mounting — no path on the host becomes the filesystem; clients speak HTTP to a port. On macOS you can then mount that endpoint with the OS’s built-in WebDAV client and get a Finder-visible volume anyway. A serve process is a full JuiceFS client, so it coexists with every other client of the filesystem — FUSE mounts elsewhere, many clients at once — with the same close-to-open consistency between clients as between mounts. Verified end-to-end with JuiceFS CE 1.4.0 against a live filesystem.

Prerequisites

  • The JuiceFS Community Edition client. Install it per the JuiceFS docs.
  • An existing CloudFS filesystem (create one), and the same environment a mount takes — the tokenized META_URL plus the AWS_* pair. Set them per Set the Environment on the mount page.

Start the WebDAV Server

On success the launcher prints OK, service is ready on "127.0.0.1:9007" and returns. The filesystem is now an HTTP endpoint — round-trip a file to confirm:
By default the endpoint is unauthenticated, which is why these examples bind to 127.0.0.1 — only processes on the same host can reach it. To serve beyond localhost, set WEBDAV_USER and WEBDAV_PASSWORD in the server’s environment before starting it; the server then returns 401 unless the request carries matching Basic credentials (curl -u agent:...). Basic auth over plain http:// sends the password — and your files — readable on the wire, so pair it with TLS (juicefs webdav serves HTTPS with --cert-file / --key-file) or keep the port reachable only over a private network or SSH tunnel. --background daemonizes the server, which is convenient interactively. Under a supervisor (launchd, systemd, a container entrypoint), drop --background and run it in the foreground — the supervisor then owns restarts, and startup errors land in its logs instead of a detached daemon’s.

Mount the WebDAV Endpoint in Finder (macOS)

macOS ships its own WebDAV filesystem — it’s what Go → Connect to Server uses. It is part of the OS, so an MDM policy that blocks third-party system extensions (the reason macFUSE won’t install) doesn’t apply to it. Point it at the local server and you get a real mounted volume — a mount of the endpoint, one hop in front of CloudFS:
The Finder-only equivalent is Cmd+K → http://127.0.0.1:9007. If Finder prompts for credentials against an anonymous server, connect as Registered User with any username and an empty password — the Guest option is rejected. Unmount with umount ~/CloudFS.

What Works Through the Mount — and What Doesn’t

Everyday file operations behave like a local directory: ls, cd, mkdir, cp, mv, cat, editing files, working in Finder — all verified against a live filesystem. But it is WebDAV underneath, not POSIX, and the difference shows at the edges:
  • No executing in place. The volume is mounted nodev,noexec,nosuid — you can read and write binaries, but running one from the mount fails with permission denied. Copy it out first.
  • Listings lag a few seconds. Apple’s WebDAV client caches directory listings, so a file another client just wrote may take a moment (or a Finder refresh) to appear.
  • Git working trees don’t work. git init inside the mount fails writing .git/config (Invalid argument). Keep repositories on a FUSE mount, which handles them fine.
  • File locks coordinate nothing. flock calls succeed, but the lock is local to your machine — the cross-client lock coordination that FUSE mounts get through the shared metadata does not ride over WebDAV. Don’t rely on locks taken through this mount.
  • Permissions are cosmetic. Every entry appears owned by your local user with -rwx------ modes, whatever a POSIX client would see.
When you need POSIX behavior — locks, executability, repositories — use a FUSE mount. For reading, writing, and shuttling files between machines, the WebDAV path is enough.

Troubleshooting

Next Steps


Concurrent Access

Source: https://developers.telnyx.com/docs/edge-compute/cloudfs/concurrent-access.md
CloudFS is a shared filesystem: the same filesystem can be mounted by many clients at once — a fleet of agents, a set of containers, several hosts — and they read and write it concurrently. Because the metadata index lives in one consistent store that every client reads and writes directly (rather than each client keeping its own copy and reconciling later), all mounts converge on the same directory tree.

Mount the Same Filesystem on Many Clients

Every client mounts with the same meta_url (token included) and the same TELNYX_API_KEY. There is nothing per-client to set up — a mount holds no server-side state — so you can add or remove clients at any time. Run the mount recipe on each host:
Distribute the token to each client however you manage secrets. If you rotate the token, already-mounted clients keep working on their existing connection; only new mounts need the new meta_url.

What One Client Sees of Another’s Writes

CloudFS gives close-to-open consistency, the standard for shared filesystems: when a client writes a file and closes it, other clients see the new contents the next time they open it. Directory operations — create, rename, delete — commit to the metadata store immediately and become visible to other clients within about a second (the lifetime of a client’s kernel metadata cache). With client A and client B both mounted at /mnt/shared:
Concurrent writes to different files are independent: many clients can each write their own files at the same time with no coordination, and every client reads back exactly what another wrote, byte-for-byte.

Coordinating Writers on the Same File

Two clients writing the same file (or the same byte range) at the same time is the one case that needs coordination — as on any shared filesystem, uncoordinated overlapping writes resolve last-writer-wins. Use file locks: CloudFS supports both BSD locks (flock) and POSIX record locks (fcntl), and JuiceFS coordinates them across clients through the shared metadata. A lock held on one host blocks a conflicting lock on another.
If B can’t acquire the lock within its timeout, flock exits non-zero and B’s command doesn’t run — so a fleet can serialize access to a shared resource (a worklog, a build output directory, a leader-election file) without any external coordinator.

Worked Example: Two Clients, One Filesystem

Two containers, each an independent client, mounting the same filesystem:

Caveats

  • Same-file, uncoordinated concurrent writes resolve last-writer-wins on overlapping regions. Use the locks above whenever more than one client may write the same file.
  • Metadata latency. Every metadata operation — open, create, rename, lock — is a round-trip to us-east-1 (see The Metadata Lane). Coordination-heavy or many-small-file workloads run faster the closer clients mount to us-east-1; bulk data throughput is unaffected.
  • One credential set per filesystem. All clients share the same meta_token and API key; there is no per-client scoping within a filesystem.

Next Steps


API Reference (CloudFS (Beta))

cloudfs filesystems

  • List CloudFS filesystems: Lists the CloudFS filesystems for the authenticated user’s organization. Results use cursor-based pagination: fetch the next page by passing `meta.cursors.afte…
  • Create a CloudFS filesystem: Creates a CloudFS filesystem. Provisioning is synchronous — typically a few seconds, up to a few minutes — and the filesystem is returned with status ready,…
  • Get a CloudFS filesystem: Retrieves a CloudFS filesystem by its ID. The returned meta_url omits the credential — the metadata token is only ever returned by create and rotate-meta-tok…
  • Update a CloudFS filesystem: Updates a CloudFS filesystem. Only name can be changed; other fields are immutable and unknown fields are rejected with a 400. Renaming to a name that alre…
  • Delete a CloudFS filesystem: Permanently deletes a CloudFS filesystem, removing its S3 bucket and its metadata database. Deletion is synchronous: the response returns the filesystem’s fina…
  • Rotate the metadata token: Issues a new metadata access token for the filesystem and returns the full filesystem, including the new meta_token and credential-bearing meta_url. The pr…