📂 Part 5: Distributed Storage with GlusterFS on Debian 13 (Trixie)
Welcome to the fifth and final installment of our “Debian 13 Clustering & Distribution” series. In the previous guide, we deployed a self-healing PostgreSQL cluster. Now, we will establish a highly available, active-active distributed file storage system for telephony media assets (such as call recordings, voicemail logs, and system music). In this tutorial, we will configure GlusterFS (Replica 3) on Debian 13, build a trusted storage pool, create replication volumes, and configure target clients with automatic failover mounts.
🏗️ Why Use Distributed Storage?
Section titled “🏗️ Why Use Distributed Storage?”In a multi-server PBX deployment, sharing files over a single server via standard NFS creates a Single Point of Failure (SPOF) and a severe I/O bottleneck.
A distributed file system like GlusterFS solves this by offering:
- Redundancy (Replica 3): Media files are written simultaneously to three nodes. If a storage node goes offline, files remain fully accessible.
- Active-Active Access: Client nodes (like Telephony application servers) can read and write to any storage node in the pool.
- Self-Healing: If a failed node is restored, GlusterFS automatically synchronizes missing block differences.
🏛️ Storage Cluster Architecture
Section titled “🏛️ Storage Cluster Architecture”Our cluster will use 3 dedicated storage nodes to run a split-brain safe Replica 3 volume.
| Role | Hostname | IP | Function |
|---|---|---|---|
| File Server 1 | fs-node-01 |
192.168.10.37 |
GlusterFS Brick Node 1 |
| File Server 2 | fs-node-02 |
192.168.10.38 |
GlusterFS Brick Node 2 |
| File Server 3 | fs-node-03 |
192.168.10.39 |
GlusterFS Brick Node 3 |
🛠️ Step 1: Environment Preparation (All 3 Storage Nodes)
Section titled “🛠️ Step 1: Environment Preparation (All 3 Storage Nodes)”Log into each storage node to perform the base installation.
1.1 Configure Hostnames
Section titled “1.1 Configure Hostnames”Assign hostnames to distinguish nodes:
# On fs-node-01hostnamectl set-hostname fs-node-01
# On fs-node-02hostnamectl set-hostname fs-node-02
# On fs-node-03hostnamectl set-hostname fs-node-031.2 Resolution IP Mappings (/etc/hosts)
Section titled “1.2 Resolution IP Mappings (/etc/hosts)”Add this mapping block to /etc/hosts on all nodes (including your VoIP/FreeSWITCH clients):
cat << 'EOF' >> /etc/hosts192.168.10.37 fs-node-01192.168.10.38 fs-node-02192.168.10.39 fs-node-03EOF1.3 Install GlusterFS Daemon
Section titled “1.3 Install GlusterFS Daemon”Debian 13 includes GlusterFS Server in its native repositories. Run the following command on all storage nodes:
apt update && apt upgrade -yapt install -y glusterfs-server1.4 Firewall Configuration (nftables)
Section titled “1.4 Firewall Configuration (nftables)”GlusterFS dynamically maps ports, but the main broker daemon listens on port 24007. To ensure simple and secure communications, allow total access between storage cluster nodes, and restrict client mount traffic.
Add these rules to /etc/nftables.conf on all 3 nodes:
cat <<EOF > /etc/nftables.conf#!/usr/sbin/nft -f
flush ruleset
table inet filter { chain input { type filter hook input priority 0; policy drop; iif "lo" accept ct state established,related accept tcp dport 22 accept ip protocol icmp accept
# Internal Storage Traffic: Total access between cluster nodes ip saddr { 192.168.10.37, 192.168.10.38, 192.168.10.39 } accept
# Client Mount Traffic: Allow VoIP subnet to access daemon and brick port ranges ip saddr { 192.168.10.0/24 } tcp dport { 24007, 24008, 49152-65535 } accept } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; }}EOF
systemctl start nftablessystemctl enable nftables🤝 Step 2: Establish the Trusted Storage Pool
Section titled “🤝 Step 2: Establish the Trusted Storage Pool”Next, we link our cluster nodes together.
2.1 Start and Enable glusterd (All 3 Nodes)
Section titled “2.1 Start and Enable glusterd (All 3 Nodes)”Start and enable the glusterd daemon across all three storage nodes before joining them to the pool:
systemctl start glusterdsystemctl enable glusterdsystemctl status glusterd2.2 Probe Peers (fs-node-01 only)
Section titled “2.2 Probe Peers (fs-node-01 only)”Run these peer commands from fs-node-01 ONLY to register the other nodes:
gluster peer probe fs-node-02gluster peer probe fs-node-03Verify that both nodes are successfully connected:
gluster peer statusExpected Output:
Number of Peers: 2
Hostname: fs-node-02Uuid: 5e612cb7-8547-4ad3-a9d1-3e4b104928dbState: Peer in Cluster (Connected)
Hostname: fs-node-03Uuid: 8cb019ef-b328-40ef-bb4b-cf109cde8e11State: Peer in Cluster (Connected)🧱 Step 3: Create the Distributed Volumes
Section titled “🧱 Step 3: Create the Distributed Volumes”With our storage pool established, we define the three replicated volumes required for the Ring2All platform: ss-recordings (for call recordings), ss-uploads (for portal branding and uploads), and ss-music (for music on hold).
3.1 Create Brick Directories (All 3 Nodes)
Section titled “3.1 Create Brick Directories (All 3 Nodes)”Create directory paths where GlusterFS will write block files:
# Run on fs-node-01, fs-node-02, and fs-node-03:mkdir -p /gluster/brick1/ss-recordingsmkdir -p /gluster/brick1/ss-uploadsmkdir -p /gluster/brick1/ss-music[!TIP] Production Best Practice: In production, do not create bricks on the server OS root partition. Instead, attach a dedicated physical storage disk (e.g.,
/dev/sdb), format it with an XFS filesystem, and mount it to your brick path to guarantee I/O isolation.
3.2 Initialize the Volumes (fs-node-01 only)
Section titled “3.2 Initialize the Volumes (fs-node-01 only)”Define the replicated volume structures:
# Initialize the recordings volumegluster volume create ss-recordings replica 3 \ fs-node-01:/gluster/brick1/ss-recordings \ fs-node-02:/gluster/brick1/ss-recordings \ fs-node-03:/gluster/brick1/ss-recordings \ force
# Initialize the uploads volumegluster volume create ss-uploads replica 3 \ fs-node-01:/gluster/brick1/ss-uploads \ fs-node-02:/gluster/brick1/ss-uploads \ fs-node-03:/gluster/brick1/ss-uploads \ force
# Initialize the music volumegluster volume create ss-music replica 3 \ fs-node-01:/gluster/brick1/ss-music \ fs-node-02:/gluster/brick1/ss-music \ fs-node-03:/gluster/brick1/ss-music \ force(We use the force flag here because we are writing to the root filesystem block loop).
3.3 Start the Replicated Volumes
Section titled “3.3 Start the Replicated Volumes”gluster volume start ss-recordingsgluster volume start ss-uploadsgluster volume start ss-musicVerify that all three volumes are started:
gluster volume info🔌 Step 4: Client Configuration (Mounting & High Availability)
Section titled “🔌 Step 4: Client Configuration (Mounting & High Availability)”To access the distributed storage pool, telephony and application servers must mount the corresponding volumes locally.
4.1 Install the Native FUSE Client
Section titled “4.1 Install the Native FUSE Client”Run the following command on all client servers (such as Telephony Server or API nodes):
apt install -y glusterfs-client4.2 Create Target Mount Points
Section titled “4.2 Create Target Mount Points”Create the directories matching each node type’s expected layout:
# On Telephony Nodes (Telephony Server):mkdir -p /var/lib/freeswitch/recordingsmkdir -p /usr/share/freeswitch/sounds/music
# On the Admin API Node:mkdir -p /var/www/softswitch/uploads4.3 Configure Automount in /etc/fstab with Failover
Section titled “4.3 Configure Automount in /etc/fstab with Failover”To ensure the storage mounts survive server restarts and automatically handle node failures, configure the /etc/fstab table using the backup-volfile-servers flag.
If the primary node fs-node-01 goes offline, the client will immediately switch to fs-node-02 or fs-node-03 to keep reads/writes alive without interrupting active services:
# On Telephony Nodes (Telephony Server):cat << 'EOF' >> /etc/fstabfs-node-01:/ss-recordings /var/lib/freeswitch/recordings glusterfs defaults,_netdev,backup-volfile-servers=fs-node-02:fs-node-03 0 0fs-node-01:/ss-music /usr/share/freeswitch/sounds/music glusterfs defaults,_netdev,backup-volfile-servers=fs-node-02:fs-node-03 0 0EOF
# On the Admin API Node:cat << 'EOF' >> /etc/fstabfs-node-01:/ss-uploads /var/www/softswitch/uploads glusterfs defaults,_netdev,backup-volfile-servers=fs-node-02:fs-node-03 0 0EOF4.4 Mount and Verify
Section titled “4.4 Mount and Verify”Trigger the mounting process and inspect the active storage:
mount -adf -h | grep -E 'recordings|music|uploads'4.5 Alternative: NAS / NFS Mount Option
Section titled “4.5 Alternative: NAS / NFS Mount Option”If your organization prefers using a pre-existing physical NAS appliance instead of building a software cluster, configure NFS client mounting on your nodes:
# Install NFS clientapt install -y nfs-common
# Create mount pointsmkdir -p /var/lib/freeswitch/recordingsmkdir -p /usr/share/freeswitch/sounds/musicmkdir -p /var/www/softswitch/uploads
# Add configuration to fstabcat << 'EOF' >> /etc/fstabnas.example.com:/recordings /var/lib/freeswitch/recordings nfs defaults,_netdev 0 0nas.example.com:/music /usr/share/freeswitch/sounds/music nfs defaults,_netdev 0 0nas.example.com:/uploads /var/www/softswitch/uploads nfs defaults,_netdev 0 0EOF
# Mountmount -a[!WARNING] Single Point of Failure (SPOF): While simpler to deploy, a single NFS NAS represents a single point of failure. Ensure your NAS architecture features redundant controllers and multi-path networking for production.
🔄 Step 5: Advanced Operations & Health Checks
Section titled “🔄 Step 5: Advanced Operations & Health Checks”Self-Healing Synchronization
Section titled “Self-Healing Synchronization”If a storage node crashes and is later restored, the cluster repairs block differences automatically in the background. To monitor progress, run:
gluster volume heal gv_recordings infoIf the output displays 0 entries, your distributed data is fully synchronized.
🏁 Series Wrap-Up
Section titled “🏁 Series Wrap-Up”Congratulations! You have completed the Debian 13 Clustering & Distribution guide series.
We have successfully covered:
- Part 1: Setting up a secure, signed public APT repository.
- Part 2: Compiling and packaging Telephony Server from source.
- Part 3: Packaging Kamailio and deploying it securely.
- Part 4: Implementing a self-healing PostgreSQL cluster using Patroni and Etcd consensus.
- Part 5: Building a replicated storage layer using GlusterFS for media file distribution.
Your infrastructure is now secure, modular, highly available, and ready for enterprise scale.

