mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-10-06 06:39:07 +00:00
Fix RQLite advertised addresses for proper cluster formation
- Add automatic external IP detection for RQLite advertised addresses - Use 0.0.0.0 for binding but actual IP for advertising to other nodes - Add -http-adv-addr and -raft-adv-addr parameters to RQLite startup - Resolves 'advertised HTTP address is not routable' error - Enables proper RQLite cluster formation between nodes
This commit is contained in:
parent
2181b5ced0
commit
79efd7b2c5
@ -3,10 +3,12 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rqlite/gorqlite"
|
||||
@ -41,12 +43,25 @@ func (r *RQLiteManager) Start(ctx context.Context) error {
|
||||
return fmt.Errorf("failed to create RQLite data directory: %w", err)
|
||||
}
|
||||
|
||||
// Get the external IP address for advertising
|
||||
externalIP, err := r.getExternalIP()
|
||||
if err != nil {
|
||||
r.logger.Warn("Failed to get external IP, using localhost", zap.Error(err))
|
||||
externalIP = "localhost"
|
||||
}
|
||||
|
||||
// Build RQLite command
|
||||
args := []string{
|
||||
"-http-addr", fmt.Sprintf("0.0.0.0:%d", r.config.RQLitePort),
|
||||
"-raft-addr", fmt.Sprintf("0.0.0.0:%d", r.config.RQLiteRaftPort),
|
||||
}
|
||||
|
||||
// Add advertised addresses if we have an external IP
|
||||
if externalIP != "localhost" {
|
||||
args = append(args, "-http-adv-addr", fmt.Sprintf("%s:%d", externalIP, r.config.RQLitePort))
|
||||
args = append(args, "-raft-adv-addr", fmt.Sprintf("%s:%d", externalIP, r.config.RQLiteRaftPort))
|
||||
}
|
||||
|
||||
// Add join address if specified (for non-bootstrap or secondary bootstrap nodes)
|
||||
if r.config.RQLiteJoinAddress != "" {
|
||||
args = append(args, "-join", r.config.RQLiteJoinAddress)
|
||||
@ -168,3 +183,96 @@ func (r *RQLiteManager) Stop() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getExternalIP attempts to get the external IP address of this machine
|
||||
func (r *RQLiteManager) getExternalIP() (string, error) {
|
||||
// Method 1: Try using `ip route get` to find the IP used to reach the internet
|
||||
if output, err := exec.Command("ip", "route", "get", "8.8.8.8").Output(); err == nil {
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "src") {
|
||||
parts := strings.Fields(line)
|
||||
for i, part := range parts {
|
||||
if part == "src" && i+1 < len(parts) {
|
||||
ip := parts[i+1]
|
||||
if net.ParseIP(ip) != nil {
|
||||
r.logger.Debug("Found external IP via ip route", zap.String("ip", ip))
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2: Get all network interfaces and find non-localhost, non-private IPs
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, iface := range interfaces {
|
||||
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
|
||||
if ip == nil || ip.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Prefer public IPs over private IPs
|
||||
if ip.To4() != nil && !ip.IsPrivate() {
|
||||
r.logger.Debug("Found public IP", zap.String("ip", ip.String()))
|
||||
return ip.String(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method 3: Fall back to private IPs if no public IP found
|
||||
for _, iface := range interfaces {
|
||||
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
|
||||
if ip == nil || ip.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Use any IPv4 address
|
||||
if ip.To4() != nil {
|
||||
r.logger.Debug("Found private IP", zap.String("ip", ip.String()))
|
||||
return ip.String(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no suitable IP address found")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user