Cómo convertir un GL.iNet Flint 3 con OpenWrt en QNetd para un clúster Proxmox
En un clúster Proxmox formado por dos nodos hay un problema bastante conocido: para mantener el quórum necesitamos evitar situaciones en las que cada nodo tenga exactamente la mitad de los votos. Una solución habitual consiste en añadir un QDevice, que utiliza un tercer equipo independiente ejecutando QNetd para actuar como árbitro. En mi caso ya tenía un QDevice funcionando, pero el QNetd estaba alojado en otra máquina. Quería eliminar esa dependencia y aprovechar un dispositivo que está prácticamente siempre encendido y que además es físicamente independiente de los servidores Proxmox: mi router GL.iNet Flint 3 (GL-BE9300). El problema es que el Flint 3 utiliza OpenWrt, no Debian, y los repositorios disponibles en mi firmware no incluyen corosync-qnetd. Importante: esta guía documenta exactamente la solución que utilicé en mi instalación. OpenWrt, GL.iNet, Debian, Corosync y Proxmox evolucionan, por lo que conviene comprobar versiones, rutas y parámetros antes de copiarlos literalmente.
En YouTube comparto más tutoriales, pruebas y domótica real. Suscribirme

Vídeo relacionado en YouTube
Video1. El entorno utilizado
En mi instalación:
Router:
GL.iNet Flint 3 / GL-BE9300
IP: 192.168.1.1
OpenWrt 23.05-SNAPSHOT
Arquitectura ARM64
Clúster:
Nombre: hectormox
Nodo 1:
miniproxmox
192.168.1.6
Nodo 2:
zimaproxmox
192.168.1.7La Debian mínima quedó instalada en:
/opt/debian-qnetd
QNetd escucha en el puerto estándar:
TCP 5403
2. Entrar por SSH al Flint 3
Desde Windows podemos utilizar directamente el cliente SSH incluido en PowerShell:
ssh root@192.168.1.1
Introducimos la contraseña de administración del router.
Una vez dentro veremos algo similar a:
BusyBox
OpenWrt
root@GL-BE9300:~#Antes de instalar absolutamente nada merece la pena descubrir qué tenemos realmente.
3. Comprobar sistema, arquitectura, paquetes y espacio disponible
Ejecutamos:
cat /etc/os-release
cat /etc/openwrt_release
uname -a
uname -m
command -v opkg
command -v apk
opkg print-architecture
df -hEn mi Flint obtuve un sistema:
OpenWrt 23.05-SNAPSHOT
aarch64
y opkg como gestor de paquetes.
También comprobé qué herramientas estaban disponibles:
command -v ar
command -v tar
command -v gzip
command -v xz
command -v wget
command -v curl
command -v mount
command -v chrootY, especialmente, si OpenWrt ya ofrecía Corosync:
opkg update
opkg list | grep -Ei 'corosync|qnetd|qdevice|libnss|libqb'En mi firmware no aparecía corosync-qnetd.
Por tanto no podíamos hacer simplemente:
opkg install corosync-qnetd
como haríamos con un paquete nativo de OpenWrt.
4. Por qué utilizar una Debian mínima dentro de OpenWrt
En lugar de intentar compilar Corosync y todas sus dependencias directamente para OpenWrt, opté por una solución bastante más sencilla:
crear una Debian ARM64 mínima dentro de una carpeta y ejecutar QNetd mediante chroot.
OpenWrt continúa siendo el sistema operativo del router. No instalamos otro kernel, no virtualizamos nada y no sustituimos el firmware.
La estructura es simplemente:
OpenWrt
└── /opt/debian-qnetd
└── Debian 12 ARM64
└── corosync-qnetdEs decir, el Flint sigue funcionando como router OpenWrt, pero dispone de un pequeño entorno Debian desde el que podemos ejecutar software que no existe en sus repositorios.
5. Instalar debootstrap en el Flint
Primero actualizamos los índices:
opkg update
Instalamos debootstrap:
opkg install debootstrap
Comprobamos que está disponible:
command -v debootstrap
debootstrap --versionY revisamos el espacio disponible:
df -h /overlay
En mi caso había varios gigabytes libres, suficiente para una Debian mínima.
6. Problema con GPG y Debian Bookworm
Aquí apareció uno de los primeros problemas específicos de mi versión de OpenWrt.
debootstrap necesita verificar las firmas de los repositorios Debian, pero el gpgv disponible inicialmente en el router era demasiado antiguo para algunas firmas utilizadas por Bookworm.
La solución fue instalar:
opkg install gpgv2
Podemos comprobarla con:
gpgv2 --version
También necesitamos las claves oficiales de Debian.
Preparamos una carpeta temporal:
BASE="/tmp/qnetd-bootstrap"
mkdir -p "$BASE"
mkdir -p "$BASE/bin"Descargamos el paquete debian-archive-keyring correspondiente a Debian Bookworm.
Aquí conviene comprobar cuál es la versión actual del paquete cuando se siga esta guía, en lugar de copiar permanentemente una URL concreta.
Una vez descargado:
DEB="$BASE/debian-archive-keyring.deb"
Extraemos su contenido:
ar p "$DEB" data.tar.xz |
xz -dc |
tar -xf - -C "$BASE"La clave queda disponible en:
KEY="$BASE/usr/share/keyrings/debian-archive-keyring.gpg"
ls -l "$KEY"Para asegurarnos de que debootstrap utiliza gpgv2, creamos un pequeño override temporal:
ln -sf /usr/bin/gpgv2 "$BASE/bin/gpgv"
Esto únicamente afectará al PATH que utilizaremos al ejecutar debootstrap.
7. Crear Debian 12 ARM64 minbase
Definimos dónde queremos instalarla:
TARGET="/opt/debian-qnetd"
Ejecutamos:
PATH="$BASE/bin:$PATH" \
debootstrap \
--arch=arm64 \
--variant=minbase \
--keyring="$KEY" \
bookworm \
"$TARGET" \
https://deb.debian.org/debianEsto descarga e instala una Debian 12 mínima dentro de:
/opt/debian-qnetd
Podemos comprobar su contenido:
ls -la /opt/debian-qnetd
Y entrar manualmente:
chroot /opt/debian-qnetd /bin/bash
Para volver a OpenWrt:
exit
8. Actualizar Debian e instalar QNetd
Desde el propio OpenWrt podemos lanzar directamente comandos dentro del chroot:
chroot "$TARGET" /usr/bin/apt-get update
Antes de instalar comprobamos que el paquete está disponible:
chroot "$TARGET" \
/usr/bin/apt-cache policy corosync-qnetdEn mi caso Debian ofrecía:
corosync-qnetd 3.0.3-1
La instalación inicial encontró algunas dependencias pendientes del entorno minbase.
Primero reparé la base de paquetes con:
chroot "$TARGET" \
/usr/bin/apt-get --no-remove -y --fix-broken installDespués instalé:
chroot "$TARGET" \
/usr/bin/apt-get install -y \
--no-install-recommends \
corosync-qnetd \
libnss3-toolsEntre las dependencias que terminó instalando Debian aparecieron bibliotecas NSS, Perl, netbase y otros paquetes necesarios.
9. /proc y /dev/pts durante la instalación
Durante la instalación aparecieron algunos avisos relacionados con /proc y /dev/pts.
Monté temporalmente:
mount -o bind \
/proc \
/opt/debian-qnetd/procY:
mount -o bind \
/dev/pts \
/opt/debian-qnetd/dev/ptsEsto nos ayudó durante la preparación de Debian.
Posteriormente comprobamos que QNetd no necesita estos bind mounts para ejecutarse normalmente, por lo que no forman parte del servicio definitivo.
10. Inicializar los certificados de QNetd
QNetd utiliza una base NSS para gestionar sus certificados.
Dentro de nuestra Debian tenemos la utilidad:
corosync-qnetd-certutil
La inicializamos desde OpenWrt:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd-certutil \
-iLa base NSS queda, vista desde OpenWrt, en:
/opt/debian-qnetd/etc/corosync/qnetd/nssdb
Podemos comprobarla con:
ls -lah \
/opt/debian-qnetd/etc/corosync/qnetd/nssdbDentro del chroot esa misma ruta sería:
/etc/corosync/qnetd/nssdb
La CA pública queda en:
/opt/debian-qnetd/etc/corosync/qnetd/nssdb/qnetd-cacert.crt
11. Comprobar el usuario coroqnetd
El paquete Debian crea un usuario específico para ejecutar QNetd.
Comprobamos sus identificadores:
chroot /opt/debian-qnetd id coroqnetd
En mi instalación obtuve:
UID 100
GID 101
Esto es importante porque más adelante ejecutaré QNetd con:
--userspec=100:101
Estos números no deben copiarse sin comprobarlos primero.
Cada instalación debe ejecutar:
chroot /opt/debian-qnetd id coroqnetd
y utilizar los valores obtenidos.
También revisamos permisos de la base NSS:
DB="/opt/debian-qnetd/etc/corosync/qnetd/nssdb"
ls -ln "$DB"En mi caso tuve que ajustar:
chgrp 101 \
"$DB/pwdfile.txt" \
"$DB/pkcs11.txt"
chmod 640 \
"$DB/pwdfile.txt" \
"$DB/pkcs11.txt"De nuevo, 101 era el GID concreto de mi instalación.
12. Probar QNetd manualmente
Antes de convertirlo en servicio es importante comprobar que el daemon realmente arranca.
Probé:
timeout -s TERM 10 \
chroot --userspec=100:101 \
/opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-f \
-4 \
-l 192.168.1.1 \
-p 5403 \
-s reqLos parámetros utilizados son:
-f: ejecutarlo en foreground.-4: utilizar IPv4.-l 192.168.1.1: dirección donde escucha QNetd.-p 5403: puerto.-s req: exigir TLS en la versión que utilizamos.
Antes de copiarlo conviene comprobar la ayuda de la versión instalada:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-h13. El problema de LD_PRELOAD de OpenWrt
Al ejecutar programas Debian desde OpenWrt aparecieron avisos relacionados con una variable LD_PRELOAD del firmware.
Para evitar que el proceso del chroot heredase variables propias de OpenWrt acabé ejecutándolo con un entorno limpio:
/usr/bin/env -i \
PATH=/usr/sbin:/usr/bin:/sbin:/bin \
...Este detalle acabó formando parte del servicio definitivo.
14. Crear el servicio QNetd en OpenWrt
Aquí tenemos una de las diferencias más importantes respecto a una Debian normal.
En Debian utilizaríamos systemd.
En OpenWrt utilizamos procd y scripts bajo:
/etc/init.d/
Creamos:
cat > /etc/init.d/qnetd-debian <<'EOF'
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=98
STOP=10
start_service() {
procd_open_instance
procd_set_param command \
/usr/bin/env -i \
PATH=/usr/sbin:/usr/bin:/sbin:/bin \
/usr/sbin/chroot --userspec=100:101 \
/opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-f -4 -l 192.168.1.1 -p 5403 -s req
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}
EOFLe damos permisos:
chmod 755 /etc/init.d/qnetd-debian
Activamos el arranque automático:
/etc/init.d/qnetd-debian enable
Podemos comprobar los enlaces creados:
ls -l /etc/rc.d/*qnetd*
En mi Flint quedaron:
/etc/rc.d/S98qnetd-debian
/etc/rc.d/K10qnetd-debian
Arrancamos el servicio:
/etc/init.d/qnetd-debian start
15. Comprobar que QNetd está funcionando
Primero buscamos el proceso:
pidof corosync-qnetd
Después comprobamos el puerto:
netstat -lntp 2>/dev/null | grep 5403
Deberíamos ver:
192.168.1.1:5403 LISTEN
También podemos comprobar el proceso completo:
ps w | grep '[c]orosync-qnetd'
Y consultar directamente a procd:
ubus call service list \
'{"name":"qnetd-debian"}'Un estado correcto contiene:
"running": true
En mi caso también podíamos ver:
/usr/bin/corosync-qnetd
-f
-4
-l 192.168.1.1
-p 5403
-s req16. Comprobar el respawn
El servicio incluye:
procd_set_param respawn 3600 5 5
Esto permite que procd vuelva a arrancar QNetd si el proceso termina inesperadamente.
Durante las pruebas llegamos a matar el proceso manualmente y comprobamos que reaparecía con otro PID y volvía a escuchar en:
192.168.1.1:5403
17. Preparar Proxmox
Ahora pasamos al primer nodo del clúster:
ssh root@192.168.1.6
Comprobamos el estado actual:
pvecm status
Y:
corosync-qdevice-tool -s
Mi clúster se llama:
hectormox
y anteriormente tenía otro QNetd en:
192.168.1.5:5403
El nuevo será:
192.168.1.1:5403
18. Hacer backup antes de cambiar QDevice
Antes de tocar certificados hice una copia de:
/etc/corosync/qdevice
/etc/pve/corosync.conf
Por ejemplo:
BACKUP="/root/qdevice-backup-$(hostname)-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "$BACKUP" \
-C / \
etc/corosync/qdevice \
etc/pve/corosync.conf
sha256sum "$BACKUP"
ls -lh "$BACKUP"No recomiendo continuar sin tener este backup.
19. Crear una base NSS nueva en Proxmox
En miniproxmox:
DIR="/root/qnetd-migration"
DB="$DIR/nssdb-new"
PASS="$DIR/pwdfile-new.txt"
mkdir -p "$DIR"
mkdir -m 700 "$DB"
: > "$PASS"
chmod 600 "$PASS"
Inicializamos NSS:
certutil -N \
-d "sql:$DB" \
-f "$PASS"20. Copiar la CA del Flint a Proxmox
Desde miniproxmox:
scp \
root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/qnetd-cacert.crt \
/root/qnetd-migration/qnetd-cacert.crtImportamos la CA:
certutil -A \
-d "sql:$DB" \
-n "QNet CA" \
-t "CT,c,c" \
-i "$DIR/qnetd-cacert.crt" \
-f "$PASS"Comprobamos:
certutil -L \
-d "sql:$DB" \
-f "$PASS"Deberíamos ver:
QNet CA CT,c,c
21. Crear el CSR del clúster
Generamos algo de entropía:
dd if=/dev/urandom \
of="$DIR/noise-new.txt" \
bs=1024 \
count=1 \
status=noneCreamos el CSR:
CSR="$DIR/qdevice-net-node.crq"
certutil -R \
-d "sql:$DB" \
-f "$PASS" \
-z "$DIR/noise-new.txt" \
-s "CN=hectormox" \
-g 3072 \
-o "$CSR"Hay que sustituir:
hectormox
por el nombre real del clúster.
Podemos comprobarlo con:
pvecm status
22. Enviar el CSR al Flint
Desde Proxmox:
scp \
"$CSR" \
root@192.168.1.1:/opt/debian-qnetd/tmp/hectormox.crqEntramos de nuevo al Flint:
ssh root@192.168.1.1
Y firmamos:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd-certutil \
-s \
-c /tmp/hectormox.crq \
-n hectormoxEl certificado firmado queda en:
/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt
23. Recuperar el certificado firmado
Desde miniproxmox:
scp \
root@192.168.1.1:/opt/debian-qnetd/etc/corosync/qnetd/nssdb/cluster-hectormox.crt \
/root/qnetd-migration/cluster-hectormox.crtPodemos convertirlo a PEM:
cd /root/qnetd-migration
openssl x509 \
-inform DER \
-in cluster-hectormox.crt \
-out cluster-hectormox.pemY verificarlo:
openssl verify \
-CAfile qnetd-cacert.crt \
cluster-hectormox.pemEl resultado correcto es:
OK
24. Importar el certificado del clúster
Añadimos el certificado firmado a NSS:
certutil -A \
-d "sql:$DB" \
-n "Cluster Cert" \
-t "u,u,u" \
-i "$DIR/cluster-hectormox.crt" \
-f "$PASS"Comprobamos:
certutil -L \
-d "sql:$DB" \
-f "$PASS"Ahora deberían aparecer:
QNet CA CT,c,c
Cluster Cert u,u,u
25. Exportar certificado y clave privada a PKCS#12
Generamos:
pk12util \
-o "$DIR/qdevice-net-node.p12" \
-d "sql:$DB" \
-k "$PASS" \
-W "" \
-n "Cluster Cert"Resultado esperado:
PKCS12 EXPORT SUCCESSFUL
Este archivo contiene una clave privada. No debe publicarse ni compartirse.
26. Preparar el segundo nodo Proxmox
Copiamos al segundo nodo:
scp \
/root/qnetd-migration/qnetd-cacert.crt \
root@192.168.1.7:/root/qnetd-migration/Y:
scp \
/root/qnetd-migration/qdevice-net-node.p12 \
root@192.168.1.7:/root/qnetd-migration/En zimaproxmox:
DIR="/root/qnetd-migration"
DB="$DIR/nssdb-new"
PASS="$DIR/pwdfile-new.txt"
CA="$DIR/qnetd-cacert.crt"
P12="$DIR/qdevice-net-node.p12"
mkdir -m 700 "$DB"
: > "$PASS"
chmod 600 "$PASS"
certutil -N \
-d "sql:$DB" \
-f "$PASS"Importamos la CA:
certutil -A \
-d "sql:$DB" \
-n "QNet CA" \
-t "CT,c,c" \
-i "$CA" \
-f "$PASS"Importamos PKCS#12:
pk12util \
-i "$P12" \
-d "sql:$DB" \
-k "$PASS" \
-W ""El resultado correcto es:
PKCS12 IMPORT SUCCESSFUL
Y comprobamos:
certutil -L \
-d "sql:$DB" \
-f "$PASS"27. Preparar una base NSS definitiva
Antes de tocar la base utilizada realmente por QDevice preparé otra carpeta:
/root/qnetd-migration/nssdb-ready
En cada nodo:
DIR="/root/qnetd-migration"
READY="$DIR/nssdb-ready"
mkdir -m 700 "$READY"
cp -a \
"$DIR/nssdb-new/." \
"$READY/"
install -m 600 \
"$DIR/pwdfile-new.txt" \
"$READY/pwdfile.txt"Comprobamos:
certutil -L \
-d "sql:$READY" \
-f "$READY/pwdfile.txt"Y podemos verificar la identidad:
certutil -L \
-d "sql:$READY" \
-n "Cluster Cert" \
-a |
openssl x509 \
-noout \
-subject \
-issuerEn mi caso:
subject=CN=hectormox
issuer=CN=QNet CA
28. Sustituir las credenciales activas
Este paso lo hicimos nodo por nodo.
Detenemos únicamente QDevice:
systemctl stop corosync-qdevice
No detenemos Corosync.
Guardamos la base antigua:
ACTIVE="/etc/corosync/qdevice/net/nssdb"
BACKUP="${ACTIVE}.pre-glinet-$(date +%Y%m%d-%H%M%S)"
mv "$ACTIVE" "$BACKUP"Copiamos la nueva:
cp -a \
/root/qnetd-migration/nssdb-ready \
"$ACTIVE"Ajustamos permisos:
chown -R root:root "$ACTIVE"
chmod 700 "$ACTIVE"
chmod 600 "$ACTIVE"/*Comprobamos:
certutil -L \
-d "sql:$ACTIVE" \
-f "$ACTIVE/pwdfile.txt"Y arrancamos QDevice:
systemctl start corosync-qdevice
Repetimos el mismo procedimiento en el otro nodo.
29. Cambiar la IP del antiguo QNetd
En mi caso QDevice ya estaba configurado contra otro servidor:
192.168.1.5
y debía pasar al Flint:
192.168.1.1
Antes hice otra copia:
cp \
/etc/pve/corosync.conf \
"/root/corosync-pre-glinet-$(date +%Y%m%d-%H%M%S).conf"El cambio fue:
- host: 192.168.1.5
+ host: 192.168.1.1
También aumentamos:
- config_version: 3
+ config_version: 4
El bloque correspondiente quedó similar a:
quorum {
device {
model: net
net {
algorithm: ffsplit
host: 192.168.1.1
tls: on
}
votes: 1
}
}Hay que tener en cuenta que config_version debe incrementarse respecto al valor que tenga cada instalación.
No hay que copiar literalmente 3 → 4.
30. Reiniciar únicamente QDevice
Después del cambio Corosync adoptó la nueva configuración, pero el proceso QDevice seguía utilizando la dirección antigua hasta reiniciarlo.
Ejecutamos:
systemctl restart corosync-qdevice
Comprobamos:
corosync-qdevice-tool -s
El resultado correcto fue:
Cluster name: hectormox
QNetd host: 192.168.1.1:5403
Algorithm: Fifty-Fifty split
State: Connected
Repetimos el reinicio de QDevice en el segundo nodo.
31. Comprobar el quórum
Ejecutamos:
pvecm status
En nuestro caso el resultado final fue:
Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Quorate: Yes
Y en la información de miembros:
0x00000001 1 A,V,NMW 192.168.1.6
0x00000002 1 A,V,NMW 192.168.1.7
0x00000000 1 Qdevice
Es decir:
miniproxmox: 1 voto.zimaproxmox: 1 voto.- QDevice/QNetd: 1 voto.
Total:
3 votos
y el quórum necesario sigue siendo:
2
32. Hacer una copia completa del QNetd del Flint
Una vez terminado todo hice una copia completa del entorno.
Definimos:
SERVICE="/etc/init.d/qnetd-debian"
BACKUP="/overlay/qnetd-backup-completo-$(date +%Y%m%d-%H%M%S).tar.gz"Paramos brevemente QNetd:
"$SERVICE" stop
Creamos el backup:
tar -czf "$BACKUP" \
-C / \
--exclude=opt/debian-qnetd/proc \
--exclude=opt/debian-qnetd/dev/pts \
--exclude=opt/debian-qnetd/run \
--exclude=opt/debian-qnetd/tmp \
opt/debian-qnetd \
etc/init.d/qnetd-debian \
etc/rc.d/S98qnetd-debian \
etc/rc.d/K10qnetd-debianArrancamos de nuevo:
"$SERVICE" start
Comprobamos la integridad:
tar -tzf "$BACKUP" >/dev/null
sha256sum "$BACKUP"
ls -lh "$BACKUP"Mi copia final ocupaba aproximadamente:
157 MB
33. Descargar el backup a Windows
Desde PowerShell:
scp -O `
root@192.168.1.1:/overlay/qnetd-backup-completo-XXXXXXXX.tar.gz `
"$env:USERPROFILE\Downloads\"Después calculamos el hash:
Get-FileHash `
"$env:USERPROFILE\Downloads\qnetd-backup-completo-XXXXXXXX.tar.gz" `
-Algorithm SHA256El valor debe coincidir exactamente con el obtenido anteriormente en el Flint.
El backup contiene certificados y claves privadas, por lo que debe almacenarse en un lugar seguro.
34. Probar el sistema después de reiniciar el Flint
No quería considerar terminado el proyecto simplemente porque funcionara después de arrancarlo manualmente.
Reinicié el Flint 3 desde su interfaz web.
Cuando volvió a estar disponible entré otra vez:
ssh root@192.168.1.1
Y comprobé primero que el script seguía ahí:
wc -l /etc/init.d/qnetd-debian
Después:
pidof corosync-qnetd
Comprobé el puerto:
netstat -lntp 2>/dev/null | grep 5403
Y finalmente procd:
ubus call service list \
'{"name":"qnetd-debian"}'En la prueba definitiva obtuve:
23 /etc/init.d/qnetd-debian
un PID válido:
28139
el puerto:
192.168.1.1:5403 LISTEN
y:
"running": true
Eso demostraba que QNetd había arrancado automáticamente tras el reboot del router.
35. Verificar que Proxmox se reconecta automáticamente
En miniproxmox:
corosync-qdevice-tool -s
El estado volvió automáticamente a:
QNetd host: 192.168.1.1:5403 State: Connected
Y:
pvecm status
volvió a mostrar:
Expected votes: 3
Total votes: 3
Quorum: 2
Quorate: Yes
Por tanto, si reiniciamos el Flint, los Proxmox pierden temporalmente el voto del QDevice, pero cuando QNetd vuelve a arrancar los QDevice se reconectan automáticamente.
36. Un problema curioso que encontramos
Durante una de las pruebas ocurrió algo extraño.
El servicio indicaba estar habilitado:
/etc/init.d/qnetd-debian enabled
pero QNetd no estaba ejecutándose.
Comprobamos:
pidof corosync-qnetd
y no obteníamos PID.
Tampoco había nada escuchando:
netstat -lntp 2>/dev/null |
grep 5403Revisamos entonces el script:
wc -l /etc/init.d/qnetd-debian
Y descubrimos:
0 /etc/init.d/qnetd-debian
El fichero se había quedado vacío.
Sin embargo, seguían existiendo:
/etc/rc.d/S98qnetd-debian
/etc/rc.d/K10qnetd-debian
Por eso OpenWrt podía indicar que el servicio estaba habilitado aunque realmente no hubiese nada que ejecutar.
Reconstruimos el script y repetimos completamente la prueba de reboot.
Desde entonces arrancó correctamente.
La conclusión es importante:
no basta con comprobar que un servicio está habilitado.
Conviene verificar además:
pidof corosync-qnetd
netstat -lntp 2>/dev/null | grep 5403
ubus call service list \ '{"name":"qnetd-debian"}'37. Diagnóstico rápido si QNetd no arranca
Primero comprobamos que el script existe y tiene contenido:
wc -l /etc/init.d/qnetd-debian
cat /etc/init.d/qnetd-debianDespués:
/etc/init.d/qnetd-debian enabled
Buscamos el proceso:
pidof corosync-qnetd
Puerto:
netstat -lntp 2>/dev/null |
grep 5403Estado en procd:
ubus call service list \
'{"name":"qnetd-debian"}'Y si queremos probar QNetd fuera de procd:
timeout 5 /usr/bin/env -i \
PATH=/usr/sbin:/usr/bin:/sbin:/bin \
/usr/sbin/chroot --userspec=100:101 \
/opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-f -4 \
-l 192.168.1.1 \
-p 5403 \
-s req
echo "EXIT=$?"Si devuelve:
124
significa que el daemon seguía vivo cuando timeout lo terminó.
En ese caso probablemente tenemos un problema con el servicio procd, no con QNetd.
38. Diagnóstico rápido desde Proxmox
Comprobamos primero los servicios:
systemctl is-active corosync
systemctl is-active corosync-qdeviceDespués:
corosync-qdevice-tool -s
Lo correcto es:
State: Connected
Y:
pvecm status
debe mostrar:
Total votes: 3
Quorate: Yes
Si aparece:
Cannot initialize CMAP service
no significa necesariamente que QNetd esté fallando.
Conviene comprobar primero:
systemctl is-active corosync
Durante mis pruebas tuvimos precisamente una incidencia de este tipo y acabó resultando ser un problema independiente de QNetd relacionado con unos montajes NFS del host Proxmox.
39. Valores que debes adaptar a tu instalación
No hay que copiar literalmente todos los valores de esta guía.
Dirección del Flint
En mi caso:
192.168.1.1
Nodos Proxmox
192.168.1.6
192.168.1.7
Nombre del clúster
hectormox
Compruébalo con:
pvecm status
Arquitectura
Mi Flint es:
ARM64
pero debemos comprobar:
uname -m
UID y GID de coroqnetd
En mi instalación:
100:101
Pero hay que consultar:
chroot /opt/debian-qnetd \
id coroqnetdRuta de Debian
Yo elegí:
/opt/debian-qnetd
No es obligatoria.
Versión de Debian
En esta guía:
Debian 12 Bookworm
TLS
Mi versión utilizaba:
-s req
Hay que comprobarlo con:
chroot /opt/debian-qnetd \
/usr/bin/corosync-qnetd \
-hconfig_version
No copies:
3 → 4
Hay que incrementar en uno el valor que tenga actualmente nuestro corosync.conf.
40. Resultado final
Después de completar todo el proceso el Flint 3 queda funcionando así:
OpenWrt
└── Debian 12 ARM64 en chroot
└── corosync-qnetdQNetd:
192.168.1.1:5403
TLS
procd
respawn
arranque automático
Y el clúster:
miniproxmox → QDevice ─┐
├──→ Flint 3 / QNetd
zimaproxmox → QDevice ─┘El resultado final que podemos comprobar con:
corosync-qdevice-tool -s
es:
QNetd host: 192.168.1.1:5403
State: Connected
Y con:
pvecm status
obtenemos:
Expected votes: 3
Total votes: 3
Quorum: 2
Quorate: Yes
Lo interesante de esta solución es que no hemos convertido el Flint 3 en un servidor Debian ni hemos sustituido OpenWrt.
El Flint continúa siendo nuestro router OpenWrt.
Simplemente aprovechamos que tenemos un dispositivo ARM64 siempre encendido, con almacenamiento suficiente y soporte para chroot, para crear una Debian mínima dedicada a ejecutar QNetd.
De esta forma podemos disponer de un tercer voto físicamente independiente para un clúster Proxmox de dos nodos sin mantener encendido otro servidor únicamente para ejecutar el árbitro.
¿Dónde comprarlo?
Si te interesa el GL.iNet GL-BE9300 Flint 3, aquí tienes las opciones de compra disponibles:
- GL.iNet GL-BE9300 Flint 3 — Analizado en el vídeo: AliExpress España · AliExpress desde Europa · AliExpress Oficial GL.iNet · Amazon


