Deployment guide

JuiceFS

Overview

JuiceFS is a distributed filesystem that separates metadata from data. File names, directory structure, permissions and the chunk layout live in a metadata engine, while file contents are stored as immutable objects in an object store. This separation lets JuiceFS present a normal POSIX mount point backed by object storage, with full support for directories, symlinks, extended attributes and random writes.

This image runs JuiceFS Community Edition 1.4.0, fully installed and configured on Ubuntu 24.04 LTS as a working single-node POSIX filesystem. Both halves are provisioned for you on a dedicated data disk, so within a few minutes of launch you have a filesystem at /mnt/juicefs that you can use like any other path.

What you get:

  • Metadata engine: PostgreSQL 16, bound to 127.0.0.1 only, with its cluster and data directory on the dedicated data disk.
  • Object store: a local directory on the same data disk, plus a read cache.
  • Mount: the volume is mounted at /mnt/juicefs by a systemd unit, juicefs-mount.service. juicefs-firstboot.service runs on first boot, and juicefs-mount.service then keeps the volume mounted.
  • JuiceFS Community Edition 1.4.0, the official upstream release, verified against the published checksum manifest and installed at /usr/local/bin/juicefs
  • An end-to-end self test at /usr/local/sbin/juicefs-selftest
  • The upstream Apache 2.0 license notice at /usr/share/doc/juicefs/LICENSE
  • A base patched at build time, with unattended security upgrades enabled, plus this deployment guide and 24/7 SecureAnyCloud support

Why PostgreSQL as the metadata engine. JuiceFS supports several metadata engines. This image uses PostgreSQL because it is transactional and durable, supports concurrent clients and is straightforward to back up with standard tooling. The single-file engines JuiceFS also offers are limited to one process at a time, which would make a concurrent mount impossible.

Boot safety. A systemd unit mounts the volume, deliberately not /etc/fstab. A FUSE entry in /etc/fstab that cannot mount blocks local-fs.target and can leave a virtual machine unbootable. With a systemd unit, a mount problem degrades gracefully: the machine still boots, SSH still works, and systemctl status juicefs-mount explains what went wrong.

Secure by default. There is no known bootstrap credential and no shared filesystem identity, because nothing is formatted when the image is built. On the first boot of your instance, a one-shot service generates a unique metadata engine password and formats a fresh volume with its own UUID for that virtual machine. It then writes the details to a root-only file at /root/juicefs-credentials.txt.

No two instances share a metadata credential, a volume UUID or an object namespace. The PostgreSQL role that owns the metadata ships with no password and no login rights until first boot sets them.

Prerequisites

  • A virtual machine deployed from this image, with SSH access as azureuser.
  • Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) to start. JuiceFS benefits from more memory for its cache, so scale up for heavier workloads.
  • No inbound network ports are required. This is a single-node filesystem appliance: the metadata engine is bound to loopback and the volume is consumed locally at /mnt/juicefs. You do not need to open any port in the network security group to use it.
  • The dedicated data disk is attached, formatted and mounted at /var/lib/juicefs automatically. Both the metadata engine and the object store live there.

Verify the filesystem is running

Connect to the virtual machine over SSH as azureuser. Confirm that JuiceFS is installed, the mount unit is active and the volume is mounted.

juicefs version
sudo systemctl is-active juicefs-mount.service mountpoint /mnt/juicefs df -h /mnt/juicefs | tail -2

The output shows the JuiceFS version, active, confirmation that /mnt/juicefs is a mountpoint, and a df line showing the filesystem as JuiceFS:sac.

The reported size is a very large logical figure, because JuiceFS presents an object-store-backed namespace rather than a fixed block device. Actual usable capacity is set by the data disk. Check it with df -h /var/lib/juicefs.

Retrieve the per-instance credentials

First boot generated the metadata engine password and the volume identity for this virtual machine and wrote them to a root-only file. Read them with sudo.

sudo grep -E '^juicefs\.' /root/juicefs-credentials.txt

The file records the volume name, the volume UUID, the mount point, the metadata engine type and URL, the metadata password and the object store location. These values are unique to this instance and are not baked into the image. Keep the file secret: the metadata password grants access to the index of your filesystem.

The same metadata password is also written to /etc/juicefs/meta.env, a root-only file with mode 0600. juicefs-mount.service reads it from there at boot. You do not need it for normal filesystem use, only for juicefs administrative subcommands that talk to the metadata engine directly.

Use the filesystem

/mnt/juicefs is a normal POSIX path. Create directories, copy files into it and read them back as you would on any other filesystem.

sudo mkdir -p /mnt/juicefs/projects echo "hello from sac JuiceFS" | sudo tee /mnt/juicefs/projects/note.txt
sudo dd if=/dev/urandom of=/mnt/juicefs/projects/data.bin bs=1M count=16 status=none sync
sudo sha256sum /mnt/juicefs/projects/data.bin ls -lh /mnt/juicefs/projects

The output shows the checksum of the 16 MiB file you just wrote and a directory listing with both files. JuiceFS supports the full range of POSIX behavior, including symlinks and extended attributes.

sudo ln -sf note.txt /mnt/juicefs/projects/note.link
sudo setfattr -n user.project -v sac /mnt/juicefs/projects/note.txt
sudo getfattr -n user.project --only-values /mnt/juicefs/projects/note.txt; echo ls -l /mnt/juicefs/projects/note.link

The extended attribute reads back as SecureAnyCloud, and the symlink resolves to note.txt. The volume is mounted with --enable-xattr, so extended attributes are stored in the metadata engine alongside the rest of the file metadata.

Confirm the metadata lives in the metadata engine

This is what distinguishes a JuiceFS volume from an ordinary directory. juicefs info reads a file's inode and its chunk and slice layout straight from the metadata engine.

sudo juicefs info /mnt/juicefs/projects/data.bin | sed -n '1,9p'

The output shows the file's inode number, its length and size, and its logical path inside the volume. The objects table below lists the individual immutable objects in the object store that hold the file's contents. A 16 MiB file is split across several 4 MiB objects.

To confirm that the metadata engine holds the filesystem index, count its tables directly in PostgreSQL.

sudo -u postgres psql -qtA -d juicefs \
  -c "SELECT count(*) FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE 'jfs%'"

The command returns the number of JuiceFS metadata tables in the database. A non-zero count confirms that the volume's index (inodes, directory entries, chunk maps and extended attributes) is stored transactionally in PostgreSQL, not merely cached in memory.

Verify the appliance end to end

The image ships a self test that proves the filesystem works, rather than merely checking that a process is running. Run it at any time.

sudo /usr/local/sbin/juicefs-selftest

The self test runs these checks:

  • Writes a known dataset through the POSIX mount and creates a symlink and an extended attribute
  • Resolves the file's inode and cross-checks that the inode is present in the PostgreSQL metadata engine
  • Performs a full unmount and remount with the cache dropped, so the read-back is served from the object store rather than a warm cache
  • Verifies that every file is byte-identical by sha256
  • Runs juicefs fsck
  • Runs two negative controls: a wrong metadata password must be refused, and a file whose backing object has been deleted must fail to read rather than silently return success

The test finishes with SELFTEST_SUCCESS.

Inspect the volume

juicefs status reports the volume's settings and its active client sessions. It talks to the metadata engine directly, so it needs the metadata password from the credentials file.

export
META_PASSWORD=$(sudo grep '^juicefs.meta.password=' /root/juicefs-credentials.txt | cut -d= -f2-)
META_URL=$(sudo grep '^juicefs.meta.url=' /root/juicefs-credentials.txt | cut -d= -f2-) sudo META_PASSWORD="$META_PASSWORD" juicefs status "$META_URL" | sed -n '1,20p'

The output shows the volume Name, its UUID, the storage type, the bucket path, the block size and the trash retention, followed by the list of active sessions.

To see how much space the volume consumes on the data disk, run:

sudo du -sh /var/lib/juicefs/data df -h /var/lib/juicefs | tail -1

Protecting the metadata engine

JuiceFS splits metadata from data, which has an important operational consequence: the metadata engine is the index of your filesystem. Every byte of data can survive intact in the object store, yet the volume is unusable without its metadata. Treat the PostgreSQL database as the part to protect.

JuiceFS can export a consistent metadata dump at any time. Run:

export
META_PASSWORD=$(sudo grep '^juicefs.meta.password=' /root/juicefs-credentials.txt | cut -d= -f2-)
META_URL=$(sudo grep '^juicefs.meta.url=' /root/juicefs-credentials.txt | cut -d= -f2-) sudo mkdir -p /var/backups/juicefs
sudo META_PASSWORD="$META_PASSWORD" juicefs dump "$META_URL" /var/backups/juicefs/meta-dump.json
sudo ls -lh /var/backups/juicefs/meta-dump.json

This writes a portable JSON dump of the entire filesystem index, which juicefs load can restore into a metadata engine. By default, JuiceFS also takes automatic periodic metadata backups into the object store under meta/.

For a second layer of protection, take a standard PostgreSQL dump as well.

sudo -u postgres pg_dump -Fc juicefs -f /var/backups/juicefs/juicefs-meta.dump
sudo ls -lh /var/backups/juicefs/juicefs-meta.dump

Copy both files, plus a record of the metadata password from /root/juicefs-credentials.txt, to a location off the instance, for example Azure Blob Storage. Schedule the backups with a cron job or systemd timer to suit your recovery objectives.

Where your data lives

This layout makes capacity planning straightforward:

  • /mnt/juicefs: the POSIX mount point your applications use
  • /var/lib/juicefs: the dedicated data disk, where everything durable lives
  • /var/lib/juicefs/data: the object store, holding the immutable objects that make up file contents
  • /var/lib/juicefs/pgdata: the PostgreSQL cluster holding the metadata engine
  • /var/lib/juicefs/cache: the local read cache, safe to clear and rebuilt on demand

Because both the object store and the metadata engine live on the dedicated data disk, usable capacity is the size of that disk. To grow the filesystem, expand the data disk in the Azure portal, then grow the filesystem on it. No JuiceFS reconfiguration is needed, because JuiceFS keeps writing objects into the same directory.

Managing the mount

A systemd unit mounts the volume, so the usual systemd commands apply.

sudo systemctl status juicefs-mount.service --no-pager | sed -n '1,12p'

To unmount and remount the volume, restart that unit rather than calling umount directly. This keeps systemd's view consistent.

sudo systemctl restart juicefs-mount.service sleep 5 mountpoint /mnt/juicefs

If the mount fails to come up, run sudo journalctl -u juicefs-mount.service to see why. The most common causes are that the metadata engine is not ready yet, or that /etc/juicefs/meta.env is missing. The mount unit does not start without that file, which stops a fresh machine from crash-looping before first boot has run.

Licensing

JuiceFS Community Edition is distributed under the Apache License 2.0. The upstream license text that governs the exact binary shipped in this image is installed at /usr/share/doc/juicefs/LICENSE.

head -3 /usr/share/doc/juicefs/LICENSE

This image ships the Community Edition. SecureAnyCloud provides the image, the deployment guide and support for the image itself. SecureAnyCloud is not affiliated with or endorsed by the JuiceFS project.

Support

SecureAnyCloud provides 24/7 support for this image. If the filesystem does not behave as this guide describes, run the self test (sudo /usr/local/sbin/juicefs-selftest) and read the mount unit's journal. Include their output with your support request.

Deploy on Azure

Launch JuiceFS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure