Drives and volumes
A drive is a named storage area for the whole cluster, such as fast or bulk. Each node that holds a drive maps its name to a folder on its own disk. A volume is one folder inside a drive, written drive/volume, that a stack mounts into a container. Clouduler keeps volumes in step across nodes, so when a node dies the service can restart on another node with its data.
This page covers replicated drives, the default. A replicated drive keeps a full copy of each volume on every node that holds the drive. For one shared copy exported over NFS, see Served drives. For getting existing files in, see Folder import. For off-site copies, see Backups.
How it works
- The cluster config declares the drive (
drives:), and each node maps it to a local folder (nodes.<name>.drives:). - The first time a stack mounts
fast/vaultwarden, the scheduler creates a volume record in the cluster database. One node is its primary, normally the node running the container. - Every
sync_interval(default 15 minutes) the primary pushes changes to the other nodes. The sync copies only what changed (block deltas for big files), and also replicates folders, permissions, owners and modification times. Files are written to a temporary name and renamed, so a reader never sees a half-written file. - Each volume has a generation number. It goes up whenever a node takes over as primary. A replica is "in sync" when its recorded generation equals the volume's generation.
- When the scheduler starts a container on a different node, it makes that node the primary. It will only choose a node that holds a usable copy. See Placement.
Because replicas catch up only on the timer, a primary that dies loses the writes made since its last sync. See Data-loss window.
Declare a drive
- Web UI
- CLI / config
Open Settings, then Storage (/settings/storage). Each drive is a card.
- Storage mode: Replicated or Served.
- Resync every: how often replicas catch up, for example
15m. Shown for replicated drives only. - Add drive creates a new card, replicated and
15mby default.
Map the drive to a folder on each node on the node's page (/nodes/atlas): in Networks and drives, click Edit and use the Drive and Local path list.
Declare the drive once, then map it on each node that should hold it:
drives:
fast:
sync_interval: 15m
mode: replicated
nodes:
atlas:
drives:
fast: /srv/fast
boreas:
drives:
fast: /srv/fast
Push the edited file to the cluster:
clouduler config reload
clouduler drive list
drive list prints one line per drive with sync= and nodes=. On a new node, clouduler init --drive fast=/srv/fast maps a drive during setup (add --drive-mode served for a served drive).
A node drive path must be absolute, and the drive must be declared under drives:. Otherwise validation fails with no drive named ... declared under drives.
Use a volume in a stack
Mount drive/volume:/path/in/container. Add :ro for read-only. The volume is created on first use.
services:
app:
image: vaultwarden/server:1.32.0
volumes:
- fast/vaultwarden:/data
fast/. mounts the whole drive. A whole-drive mount must be pinned with x-clouduler.node to the drive's single real holder (for a replicated drive, every node that implements it, so in practice only a drive held by one node). See the stack spec.
Anonymous volumes (a bare /path with no drive) are silently dropped (confirmed in the scheduler's spec conversion).
Look at drives and volumes
- Web UI
- CLI / config
Open Storage (/storage). The Volumes tab shows a card per drive (mode, sync interval, a Fullest node meter) and a Volumes table with columns Volume, Generation, Primary, Replicas and State.
Click Open fast for the drive page (/storage/drives/fast): its nodes, an About list, its volumes and its backup schedules.
State badges: In sync, Syncing, Sync refused, Frozen, Looks empty.
clouduler drive list # drives, sync interval, nodes
clouduler status # lagging volumes appear in the problem list
There is no CLI command to list volumes (volume has only freeze and unfreeze).
The Sync button does not sync now
Sync on a volume row only bumps the generation. The data still moves at the next scheduled sync. To force an immediate push, use clouduler volume unfreeze (it pushes this node's copy to the others right away) or Folder import.
Freeze a volume to edit it by hand
Freezing pauses replication of one volume so you can change its files on this node without a sync overwriting them. If containers on other nodes use the volume, volume freeze refuses; add --force to stop them. You cannot freeze a served volume.
- Web UI
- CLI / config
On the volumes table, click Freeze on the row and confirm Freeze fast/vaultwarden? ("Containers using it are stopped so you can edit its files by hand. Unfreeze it to resume replication."). The UI does not send --force, so freezing a volume that is in use on another node fails from the UI and nothing is stopped. Use the CLI with --force in that case.. A is frozen banner appears with Unfreeze.
Run on the node whose copy you want to keep:
clouduler volume freeze fast/vaultwarden # fails if other nodes run containers using it
clouduler volume freeze fast/vaultwarden --force # stop those containers instead
# ... edit the files in the local folder ...
clouduler volume unfreeze fast/vaultwarden # this node's copy becomes the primary, pushed out now
clouduler volume unfreeze fast/vaultwarden --no-start # leave the containers --force stopped
Unfreezing bumps the generation with the frozen node as primary, then waits for the other nodes to catch up before starting containers. The CLI waits up to one hour. The web UI returns immediately and finishes in the background: it waits 120 seconds for replicas, then starts the containers even if some nodes are still behind. If replicas are still behind after the CLI's hour, the CLI prints how many containers it left stopped and exits 0.
Data-loss window
Replicated sync is periodic. If the primary node dies, the new node starts from the freshest copy it can find, and writes made since the last sync are lost. With the default sync_interval: 15m that can be up to 15 minutes. Shorten sync_interval for drives that matter, and take Backups for protection against more than a node failure.
Syncs also pause while the cluster has no quorum. See Failover.
When a sync is refused
Clouduler refuses a sync that would wipe a populated copy: a source that is empty over a populated destination, or a destination of 200 or more files where the source has less than a twentieth of them. The volume row shows fast/vaultwarden refused to sync with the reason. A volume is marked Looks empty only after two consecutive empty scans. The UI deliberately has no "pick the winner" button. Inspect the copies (Inspect shows file count, bytes and newest file per node), decide which one is right, and fix it by hand with freeze and unfreeze.
Delete everywhere (in the Inspect sheet) removes the volume from every node and cannot be undone; you must type the volume id to confirm.
Disk space
Each node reports disk use every 60 seconds. The alert node.disk_low fires at 90% (warning) and 95% (critical) of the disk holding any drive the node holds data for, replicated drives included (not the mountpoint of a served drive that lives on another node). There are no quotas: nothing limits how much a drive or volume can grow. See Alerts.
Options
durationdefault 15mreplicated | serveddefault replicatedlist of node namesdefault []nodes.<name>.drives.<drive>requiredabsolute pathno defaultstack volume stringdefault rwstack volume stringno default