SAUNAFS-URAFT.CFG(5)

πŸ“¦
version 5.8.0 Β· 4 versions
, in ubuntu stonking

πŸ’– SAUNAFS-URAFT.CFG(5) πŸ’–

okay so like, this is the manual page for saunafs-uraft.cfg, the main configuration file for saunafs-uraft ✨ lowkey iconic, highkey essential, fr fr.

🌸 NAME 🌸

saunafs-uraft.cfg β€” the main configuration file for saunafs-uraft 🫢

✨ DESCRIPTION ✨

The file saunafs-uraft.cfg holds the configuration of the SaunaFS HA suite. it's giving "the blueprint for your whole high-availability setup" πŸ’…

This config gets consumed by two very important besties:

  • saunafs-uraft (the daemon) β€” it eats up the election parameters, the status port, and the timeouts πŸ—³οΈ
  • saunafs-uraft-helper (the helper script) β€” it takes the floating IP network details and handles local sfsmaster management 🌐

πŸŽ€ SYNTAX πŸŽ€

the vibe is:

OPTION = VALUE

and literally any line that starts with a # character? ignored. not even invited to the party πŸ™ˆ


πŸ”₯ OPTIONS πŸ”₯

here come the configuration options, bestie. buckle up πŸ’œ

  • URAFT_NODE_ADDRESS β€” holds an IP address or hostname of a uraft node, and it may include a port too. you're gonna specify this option multiple times so it covers every single node in the cluster, no node left behind πŸ‘‘

Example:

URAFT_NODE_ADDRESS = node1:9427
URAFT_NODE_ADDRESS = node2
URAFT_NODE_ADDRESS = 192.168.0.1:9427
  • URAFT_ID β€” this one is strictly connected with the options above πŸ”— like, they're besties, you can't split them.

It identifies which node this uraft instance is running on. node numbers start from 0 and follow the same order as the URAFT_NODE_ADDRESS entries. so like, order matters, don't be out here shuffling them.

For example, if this configuration lives on the node with hostname node2, then its URAFT_ID should be set to 1.

  • LOCAL_MASTER_ADDRESS β€” specifies an address of the local SaunaFS master server (default: localhost). 🏠
  • LOCAL_MASTER_MATOCL_PORT β€” specifies a client port of the local SaunaFS master server (default: 9421). πŸšͺ
  • URAFT_PORT β€” the UDP port used for uRaft peer-to-peer messages. this port must be reachable between all voting nodes, periodt. (default: 9427). πŸ“‘
  • URAFT_STATUS_PORT β€” the TCP port for the uRaft status endpoint. this endpoint is genuinely useful for debugging and automated tests πŸ§ͺ (default: 9428).
  • URAFT_FLOATING_IP β€” the floating IP to be used as an active master. 🌊
  • URAFT_FLOATING_NETMASK β€” the network mask matching the floating IP configuration. 🎭
  • URAFT_FLOATING_IFACE β€” the network interface where the floating IP should be managed (example: eth0). πŸ”Œ
⚠️ Important, bestie, listen up: If the network interface used for the floating IP becomes unavailable, the failover mechanism will not restore it. As a result, the floating IP cannot be recovered, causing SaunaFS services that depend on it to become unavailable. πŸ’€ The failover mechanism is based on the URAFT_FLOATING_IP_CHECK_PERIOD option. See its documentation for more details.
  • ELECTION_TIMEOUT_MIN β€” [advanced] minimal timeout in milliseconds for the election algorithm. (default: 400) πŸ—³οΈ
  • ELECTION_TIMEOUT_MAX β€” [advanced] maximal timeout in milliseconds for the election algorithm. (default: 600) πŸ—³οΈ
  • URAFT_ELECTOR_MODE β€” [advanced] controls the election role of this node. 🎭
    • If set to 0 (Default value), the node can both vote in LEADER elections and be elected as the new leader. πŸ‘‘
    • If set to 1, the node acts as an elector only: it participates in voting for a new leader, but cannot itself be elected leader. πŸ—³οΈ

When a node runs in elector mode, the metadata service is not required, which reduces its memory consumption. 🧠✨

  • HEARTBEAT_PERIOD β€” [advanced] period in milliseconds between subsequent heartbeat messages. (default: 20) πŸ’“
  • LOCAL_MASTER_CHECK_PERIOD β€” [advanced] period in milliseconds between checking whether the local master is alive. This value drives how frequently the daemon calls saunafs-uraft-helper isalive on metadata-capable nodes. (default: 250) πŸ’—
  • URAFT_FLOATING_IP_CHECK_PERIOD β€” [advanced] period in milliseconds between checking whether the floating IP is alive. A value of 0 disables floating IP monitoring and its automatic recovery mechanism. Adjust this setting based on network stability and failover requirements. (default: 500) 🌊
  • URAFT_CHECK_CMD_PERIOD β€” [advanced] period in milliseconds between checks of long-running helper commands (promotion/demotion). (default: 100). ⏱️
  • URAFT_GETVERSION_TIMEOUT β€” [advanced] timeout in milliseconds for helper commands that are expected to be fast, such as:
    • saunafs-uraft-helper metadata-version
    • saunafs-uraft-helper isalive

If this timeout is too low, the daemon may repeatedly log timeouts and keep a node blocked for promotions (blocked_promote=1), preventing elections. (default: 100). 😭

  • URAFT_PROMOTE_TIMEOUT β€” [advanced] timeout in milliseconds for promotion (saunafs-uraft-helper promote). (default: 1000000000). ⬆️
  • URAFT_DEMOTE_TIMEOUT β€” [advanced] timeout in milliseconds for demotion (saunafs-uraft-helper demote). (default: 1000000000). ⬇️
  • URAFT_DEAD_HANDLER_TIMEOUT β€” [advanced] timeout in milliseconds for the dead handler (saunafs-uraft-helper dead). (default: 1000000000). πŸ’€
  • QUORUM_LOSS_GRACE_HEARTBEATS β€” [advanced] number of consecutive missed heartbeats allowed before quorum is considered lost. πŸ’”

This parameter defines how many heartbeats may be missed in a row before the system declares quorum loss and demotes the current Leader. Increasing this value helps tolerate short-lived network glitches or transient latency spikes, reducing unnecessary demotions and improving overall cluster stability. The default value is 5.


πŸ’« TIMING RELATIONSHIPS πŸ’«

Raft-style leader election relies on the relationship between heartbeat and election timeouts. like, they're in a situationship and you have to keep it balanced 🫢

At a high level:

  • Heartbeats are sent every HEARTBEAT_PERIOD. πŸ’“
  • A follower starts an election if it has not observed a valid leader heartbeat for a duration between ELECTION_TIMEOUT_MIN and ELECTION_TIMEOUT_MAX. πŸ—³οΈ

Practical guidance, bestie, take notes πŸ“:

  • Choose election timeouts substantially larger than the heartbeat period. A common starting point is:
ELECTION_TIMEOUT_MIN >= 10 * HEARTBEAT_PERIOD
  • Keep ELECTION_TIMEOUT_MAX close to ELECTION_TIMEOUT_MIN (for example 1.5x) to reduce worst-case failover time, but not so close that elections synchronize. ⏳
  • QUORUM_LOSS_GRACE_HEARTBEATS effectively controls demotion sensitivity:
demotion window ~= QUORUM_LOSS_GRACE_HEARTBEATS * HEARTBEAT_PERIOD
  • In WAN/VPN environments with packet loss, consider increasing this value and/or increasing HEARTBEAT_PERIOD. 🌐

✨ EXAMPLES ✨

okay bestie, this is the part where it gets real πŸ’– Three whole complete configs for three whole complete vibes. Copy them, tweak them, live your truth.

Each node uses the same file contents except for URAFT_ID (and optionally URAFT_ELECTOR_MODE). Like, that's the only difference between your babies. Adorable. 🫢


🏑 Example 1: LAN / Low Packet Loss

This config targets low-latency LAN environments where packet loss is rare and leader churn is unlikely. Basically: everyone's in the same room, packets are behaving, nobody's fighting over the crown. πŸ‘‘

# Cluster membership
URAFT_NODE_ADDRESS = 10.0.0.11:9427
URAFT_NODE_ADDRESS = 10.0.0.12:9427
URAFT_NODE_ADDRESS = 10.0.0.13:9427

# Per-node setting (0, 1, or 2 depending on which node)
URAFT_ID = 0

# Local metadata service
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
LOCAL_MASTER_CHECK_PERIOD = 250

# Raft timing
HEARTBEAT_PERIOD = 20
ELECTION_TIMEOUT_MIN = 400
ELECTION_TIMEOUT_MAX = 600
QUORUM_LOSS_GRACE_HEARTBEATS = 10

# Helper timeouts
URAFT_GETVERSION_TIMEOUT = 200

# Status endpoint
URAFT_STATUS_PORT = 9428

# Floating IP
URAFT_FLOATING_IP = 10.0.0.100
URAFT_FLOATING_NETMASK = 24
URAFT_FLOATING_IFACE = eth0
URAFT_FLOATING_IP_CHECK_PERIOD = 500

🌍 Example 2: WAN/VPN / Higher Loss and Jitter

This config targets deployments where voting nodes communicate across a WAN, or where the floating IP is effectively reached via VPN. the drama of distance 😭

Symptoms of overly aggressive timing in these environments can include leader ping-pong effect (rapid leadership churn) and prolonged periods without a stable Leader. Not the glow-up we wanted, bestie πŸ’€

The strategy is:

  • Send heartbeats less frequently.
  • Use larger election timeouts.
  • Increase quorum-loss hysteresis.
# Cluster membership (example with 5 voters)
URAFT_NODE_ADDRESS = 172.18.0.4:9427
URAFT_NODE_ADDRESS = 172.18.0.5:9427
URAFT_NODE_ADDRESS = 172.18.0.6:9427
URAFT_NODE_ADDRESS = 172.18.0.7:9427
URAFT_NODE_ADDRESS = 172.18.0.8:9427

# Per-node setting
URAFT_ID = 0

# Optional: elector nodes (set URAFT_ELECTOR_MODE=1 on electors)
URAFT_ELECTOR_MODE = 0

# Local metadata service
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
LOCAL_MASTER_CHECK_PERIOD = 500

# Raft timing (slower but more stable over lossy links)
HEARTBEAT_PERIOD = 100
ELECTION_TIMEOUT_MIN = 3000
ELECTION_TIMEOUT_MAX = 4500
QUORUM_LOSS_GRACE_HEARTBEATS = 30

# Helper timeouts (avoid timeouts during transient stalls)
URAFT_GETVERSION_TIMEOUT = 1000

# Status endpoint
URAFT_STATUS_PORT = 9428

# Floating IP
URAFT_FLOATING_IP = 172.18.0.10
URAFT_FLOATING_NETMASK = 32
URAFT_FLOATING_IFACE = lo
URAFT_FLOATING_IP_CHECK_PERIOD = 1000

πŸ‘‘ Example 3: 5-Node Topology (3 Metadata + 2 Electors)

This example shows a common production topology:

  • 3 metadata-capable nodes (eligible to become Leader)
  • 2 elector-only nodes (vote in elections but never become Leader)

This reduces the risk that a metadata node becomes unavailable due to resource pressure, while still increasing the number of voters to improve resilience. it's giving main character energy with a solid supporting cast πŸŽ€

Important Elector nodes are still voting members. They must have stable network connectivity to the metadata nodes; otherwise they can contribute to leader churn.

All nodes share the same base configuration. Per-node differences are:

  • URAFT_ID must be unique and match the node's position in URAFT_NODE_ADDRESS.
  • URAFT_ELECTOR_MODE must be set to 1 on elector nodes.
# Cluster membership (5 voters total)
URAFT_NODE_ADDRESS = 10.0.0.11:9427   # metadata
URAFT_NODE_ADDRESS = 10.0.0.12:9427   # metadata
URAFT_NODE_ADDRESS = 10.0.0.13:9427   # metadata
URAFT_NODE_ADDRESS = 10.0.0.21:9427   # elector-only
URAFT_NODE_ADDRESS = 10.0.0.22:9427   # elector-only

# Per-node setting
URAFT_ID = 0

# Set to 0 on metadata nodes (IDs 0-2), set to 1 on elector nodes (IDs 3-4)
URAFT_ELECTOR_MODE = 0

# Local metadata service (used only on metadata nodes)
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
LOCAL_MASTER_CHECK_PERIOD = 250

# Raft timing (LAN-friendly defaults)
HEARTBEAT_PERIOD = 20
ELECTION_TIMEOUT_MIN = 400
ELECTION_TIMEOUT_MAX = 600
QUORUM_LOSS_GRACE_HEARTBEATS = 10

# Helper timeouts
URAFT_GETVERSION_TIMEOUT = 200

# Status endpoint
URAFT_STATUS_PORT = 9428

# Floating IP (managed by the Leader, which must be a metadata node)
URAFT_FLOATING_IP = 10.0.0.100
URAFT_FLOATING_NETMASK = 24
URAFT_FLOATING_IFACE = eth0
URAFT_FLOATING_IP_CHECK_PERIOD = 500

🩹 TROUBLESHOOTING 🩹

Something's acting up? bestie, breathe, we got you 🫢

  • Repeated "Isalive timeout" lines β€” Increase URAFT_GETVERSION_TIMEOUT and ensure the local sfsmaster responds promptly to sfsmaster -o ha-cluster-managed isalive.
  • Nodes stuck with blocked_promote=1 β€” This indicates the daemon is refusing to allow leader promotion on that node. The most common causes are repeated isalive timeouts or repeated dead status.
  • Leader churn / ping-pong leadership β€” Increase election timeouts and quorum-loss grace, and ensure voting nodes have stable connectivity.

πŸ› REPORTING BUGS πŸ›

Report bugs to the GitHub repository https://github.com/leil-io/saunafs as an issue. your bug reports are valid and I love them πŸ’œ


Copyright 2008-2009 Gemius SA

Copyright 2013-2019 Skytechnology sp. z o.o.

Copyright 2023 Leil Storage OÜ

SaunaFS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.

SaunaFS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with SaunaFS. If not, see http://www.gnu.org/licenses/.

no cap: that "WITHOUT ANY WARRANTY" part is real, don't come for me πŸ’€


πŸ¦‹ SEE ALSO πŸ¦‹


okay that's literally the whole page, bestie πŸ’– this was SAUNAFS-URAFT.CFG(5), dated 2026-07-29, and you read every last bit of it β€” obsessed with you, honestly ✨ go forth and configure your cluster, you've got this πŸŽ€πŸ’…

πŸ“¦ where this page comes from