Non-voting placeholder node in a 2-node Proxmox cluster

How to create a non-voting placeholder node in a two-server Proxmox cluster?

In a two-node Proxmox cluster, Corosync’s quorum mechanism can quickly become a sticking point: if the “main” node goes down, the “secondary” node finds itself alone and loses quorum, which makes the cluster unusable. The more nodes you have, the more voters and capacity you have to work with in your cluster.

Here, we want to have a second Proxmox server that doesn’t actually take part in quorum decisions. This prevents the cluster from locking up when only a single node is active, while still keeping the ability to run demo virtual machines on the secondary server. This article describes how to disable the secondary node’s Corosync vote and ensure the cluster’s stability.

I needed to build this kind of two-node cluster for my PVMSS application, to test the application’s capabilities against a Proxmox cluster. However, I don’t need several worker nodes, only one will be active.

To avoid the “split-brain” problem while keeping the second server solely as a test/placeholder machine, you need to:

  1. Remove its voting right (weight = 0).
  2. Tell Corosync that this is a two-node cluster, where quorum must be calculated based on a single real vote.

The heart of the problem lies in the votes parameter. By assigning votes: 0 to the secondary node, you remove it from the quorum calculation. You also tell Corosync that it should expect only a single real vote (expected_votes: 1) and you enable the special two-node mode (two_node: 1). This combination ensures the cluster works as long as the main node is online, and that the second node causes no “split-brain”.

Modify the corosync.conf file on the main node#

The corosync.conf file cannot be modified while the services that use it are running. Log in to the main node, where you’ll make the changes. Stop the corosync and pve-cluster services:

bash
systemctl stop pve-cluster
systemctl stop corosync

Now, you need to use the pmxcfs command to explore the Proxmox filesystem and make changes to it. Run pmxcfs -l, and the following messages should appear:

bash
[main] notice: resolved node name '<nom_node>' to '<ip_node>' for default node IP address
[main] notice: forcing local mode (although corosync.conf exists)

Before making any changes, it’s essential to create a backup copy of the configuration file with a simple “cp”: cp /etc/pve/corosync.conf /etc/pve/corosync.conf.bak.

Edit the file /etc/pve/corosync.conf and add the following changes:

bash
totem {
    ...
    config_version: 2 # increment this value before saving the corosync.conf file
    ...
}

nodelist {
    node {
        name: nom_node1
        nodeid: 1
        quorum_votes: 1          # main node: normal voting right
        ...
    }
    node {
        name: nom_node2
        nodeid: 2
        quorum_votes: 0          # secondary node: no voting right, set to 0
        ...
    }
}

quorum {
    provider: corosync_votequorum
    expected_votes: 1      # The quorum expects only 1 real vote
    two_node: 1            # Enables "two-node" mode (avoids split-brain)
    wait_for_all: 0
}
  • quorum_votes: 0 removes the second node’s voting right.
  • expected_votes: 1 indicates that quorum will be reached as soon as a single vote (that of the main node) is present.
  • two_node: 1 enables the special two-node mode: if the main node disappears, the second node keeps working in “standalone” mode (no cluster lockup), but it won’t be able to take the main node’s place until quorum is restored.
  • wait_for_all: 0 prevents corosync from waiting for the votes of all the cluster members.

Save the changes made to the file, exit the local mode of the pmxcfs command, and restart the services:

bash
killall pmxcfs && systemctl restart corosync.service pve-cluster.service

The actions will be replicated to the second node. If that’s not the case, log in to the second node, restart the pve-cluster and corosync services, then make sure the /etc/pve/corosync.conf file is identical to the first node’s.

With the pvecm status command, check that the cluster’s second machine no longer has its voting right:

bash
root@node1:~# pvecm status
Cluster information
-------------------
Name:             clustername
Config Version:   3
Transport:        knet
Secure auth:      on

Quorum information
------------------
Date:             Sat Nov  1 21:36:19 2025
Quorum provider:  corosync_votequorum
Nodes:            2
Node ID:          0x00000001
Ring ID:          1.266
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   1
Highest expected: 1
Total votes:      1
Quorum:           1
Flags:            2Node Quorate WaitForAll

Membership information
----------------------
    Nodeid      Votes Name
0x00000001          1 172.16.0.1 (local)
0x00000002          0 172.16.132.240

Result#

The secondary server becomes a “placeholder node”: it stays visible in the cluster, can host test VMs, but never influences Corosync’s decision-making process. The cluster remains fully functional even if the main node goes down, thanks to the two_node mode.

Sources#

Related articles

#blog No image
#homelab

My homelab for 2024

Following on from the previous article (available at this address), I recently adopted an approach that had long been neglected, namely setting up a real homelab with dedicated machines. After much hesitation, I seized the opportunity that presented itself, believing that it was time to move towards this approach. So here we are with version 8 for 2024, comprising the following equipment: Mac Mini M1 ; MacBook Air M1 ; 4x Chuwi Larkbox X (Intel N100, 12 Gb de RAM DDR5 + 1 NVMe 512 Gb par hôte) ; My “old” PC tower, with a dual boot (Ubuntu LTS 22.04 et Windows 11). As my role and ambitions have evolved, I’ve found it necessary to adapt my hardware to ensure rapid and optimal operation. From now on, my main focus will be on automating platforms, from infrastructure to middleware.

Read more

Latest in #proxmox