Switch node startup to YAML config files

Update Makefile, README, and .gitignore to use configs/ Add YAML config
loading to node main.go Add gopkg.in/yaml.v3 dependency Remove unused
IsBootstrap field from NodeConfig
This commit is contained in:
anonpenguin 2025-08-14 15:49:07 +03:00
parent a6129d3fc2
commit 271d7bbafb
7 changed files with 153 additions and 38 deletions

2
.gitignore vendored
View File

@ -71,3 +71,5 @@ data/*
data/bootstrap/rqlite/ data/bootstrap/rqlite/
.env.* .env.*
configs/

View File

@ -30,22 +30,20 @@ test:
# Run bootstrap node (auto-selects identity and data dir) # Run bootstrap node (auto-selects identity and data dir)
run-node: run-node:
@echo "Starting bootstrap node..." @echo "Starting bootstrap node with config..."
go run ./cmd/node --data ./data/bootstrap --p2p-port $${P2P:-4001} --rqlite-http-port $${HTTP:-5001} --rqlite-raft-port $${RAFT:-7001} --adv-addr $${ADV_ADDR:-127.0.0.1} --disable-anonrc go run ./cmd/node --config configs/bootstrap.yaml
# Run second node (regular) - requires join address of bootstrap node # Run second node (regular) - requires join address of bootstrap node
# Usage: make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002 # Usage: make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002
run-node2: run-node2:
@echo "Starting regular node2..." @echo "Starting regular node2 with config..."
@if [ -z "$(JOINADDR)" ]; then echo "ERROR: Provide join address: make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 [HTTP=5002 RAFT=7002 P2P=4002]"; exit 1; fi go run ./cmd/node --config configs/node.yaml
go run ./cmd/node --id node2 --data ./data/node2 --p2p-port $${P2P:-4002} --rqlite-http-port $${HTTP:-5002} --rqlite-raft-port $${RAFT:-7002} --rqlite-join-address $(JOINADDR)
# Run third node (regular) - requires join address of bootstrap node # Run third node (regular) - requires join address of bootstrap node
# Usage: make run-node3 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5003 RAFT=7003 P2P=4003 # Usage: make run-node3 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5003 RAFT=7003 P2P=4003
run-node3: run-node3:
@echo "Starting regular node3..." @echo "Starting regular node3 with config..."
@if [ -z "$(JOINADDR)" ]; then echo "ERROR: Provide join address: make run-node3 JOINADDR=/ip4/127.0.0.1/tcp/5001 [HTTP=5003 RAFT=7003 P2P=4003]"; exit 1; fi go run ./cmd/node --config configs/node.yaml
go run ./cmd/node --id node3 --data ./data/node3 --p2p-port $${P2P:-4003} --rqlite-http-port $${HTTP:-5003} --rqlite-raft-port $${RAFT:-7003} --rqlite-join-address $(JOINADDR)
# Run basic usage example # Run basic usage example
run-example: run-example:
@ -150,9 +148,9 @@ test-consensus: build
# Start development cluster (requires multiple terminals) # Start development cluster (requires multiple terminals)
dev-cluster: dev-cluster:
@echo "To start a development cluster, run these commands in separate terminals:" @echo "To start a development cluster, run these commands in separate terminals:"
@echo "1. make run-node # Start bootstrap node" @echo "1. make run-node # Start bootstrap node (uses configs/bootstrap.yaml)"
@echo "2. make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002" @echo "2. make run-node2 # Start second node (uses configs/node.yaml)"
@echo "3. make run-node3 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5003 RAFT=7003 P2P=4003" @echo "3. make run-node3 # Start third node (uses configs/node.yaml)"
@echo "4. make run-example # Test basic functionality" @echo "4. make run-example # Test basic functionality"
@echo "5. make cli-health # Check network health" @echo "5. make cli-health # Check network health"
@echo "6. make cli-peers # List peers" @echo "6. make cli-peers # List peers"

View File

@ -109,13 +109,15 @@ make build
```bash ```bash
make run-node make run-node
# Or manually: # Or manually:
go run ./cmd/node -data ./data/bootstrap -p2p-port 4001 -rqlite-http-port 5001 -rqlite-raft-port 7001 go run ./cmd/node --config configs/bootstrap.yaml
``` ```
### 4. Start Additional Nodes ### 4. Start Additional Nodes
```bash ```bash
go run ./cmd/node -id node2 -data ./data/node2 -rqlite-http-port 5002 -rqlite-raft-port 7002 -p2p-port 4002 --disable-anonrc make run-node2
# Or manually:
go run ./cmd/node --config configs/node.yaml
``` ```
### 5. Test with CLI ### 5. Test with CLI
@ -174,23 +176,87 @@ sudo journalctl -u debros-node.service -f
## Configuration ## Configuration
### YAML Config Example (`/opt/debros/configs/node.yaml`) ### Example Configuration Files
#### `configs/bootstrap.yaml`
```yaml ```yaml
node: node:
data_dir: "/opt/debros/data/node" id: ""
key_file: "/opt/debros/keys/node/identity.key"
listen_addresses: listen_addresses:
- "/ip4/0.0.0.0/tcp/4001" - "/ip4/0.0.0.0/tcp/4001"
solana_wallet: "YOUR_WALLET_ADDRESS" data_dir: "./data/bootstrap"
max_connections: 100
disable_anonrc: true
database: database:
data_dir: "./data/db"
replication_factor: 3
shard_count: 16
max_database_size: 1073741824
backup_interval: 24h
rqlite_port: 5001 rqlite_port: 5001
rqlite_raft_port: 7001 rqlite_raft_port: 7001
rqlite_join_address: "" # Bootstrap node does not join
discovery:
bootstrap_peers: []
discovery_interval: 15s
bootstrap_port: 4001
http_adv_address: "127.0.0.1"
raft_adv_address: ""
security:
enable_tls: false
private_key_file: ""
certificate_file: ""
auth_enabled: false
logging: logging:
level: "info" level: "info"
file: "/opt/debros/logs/node.log" format: "console"
output_file: ""
```
#### `configs/node.yaml`
```yaml
node:
id: "node2"
listen_addresses:
- "/ip4/0.0.0.0/tcp/4002"
data_dir: "./data/node2"
max_connections: 50
disable_anonrc: true
database:
data_dir: "./data/db"
replication_factor: 3
shard_count: 16
max_database_size: 1073741824
backup_interval: 24h
rqlite_port: 5002
rqlite_raft_port: 7002
rqlite_join_address: "http://127.0.0.1:5001"
discovery:
bootstrap_peers:
- "/ip4/127.0.0.1/tcp/4001/p2p/<YOUR_BOOTSTRAP_PEER_ID>"
discovery_interval: 15s
bootstrap_port: 4002
http_adv_address: "127.0.0.1"
raft_adv_address: ""
security:
enable_tls: false
private_key_file: ""
certificate_file: ""
auth_enabled: false
logging:
level: "info"
format: "console"
output_file: ""
``` ```
### Flags & Environment Variables ### Flags & Environment Variables

View File

@ -1,19 +1,19 @@
# DeBros Network: A Peer-to-Peer Decentralized Database Ecosystem # DeBros Network: A Peer-to-Peer Decentralized Development Ecosystem
**DeBros** **DeBros**
info@debros.io info@debros.io
https://debros.io https://debros.io
August 2, 2025 August 14, 2025
## Abstract ## Abstract
We propose a decentralized ecosystem, the DeBros Network, enabling peer-to-peer application deployment and operation across a global network of nodes, free from centralized control. Built with Go and LibP2P for robust networking, RQLite for distributed consensus, and integrated with the Solana blockchain for identity and governance, the network provides a resilient, privacy-first platform for decentralized applications. Participation is governed by NFT ownership and token staking, with demonstrated applications like Anchat showcasing real-world messaging capabilities. The architecture eliminates single points of failure while maintaining developer simplicity and end-user accessibility. We propose a decentralized development ecosystem, the DeBros Network, enabling peer-to-peer application deployment and operation across a global network of nodes, free from centralized control. Built LibP2P for robust networking, RQLite for distributed consensus, and integrated with the blochains like Etherium or Solana for identity and governance, the network provides a resilient, privacy-first platform for decentralized development. Participation is governed by NFT ownership and token staking, with demonstrated applications like Anchat showcasing real-world messaging capabilities. The architecture eliminates single points of failure while maintaining developer simplicity and end-user accessibility.
## 1. Introduction ## 1. Introduction
Centralized systems dominate modern technology, imposing control over data, access, and development through single points of failure and intermediaries. These structures compromise privacy, resilience, innovation, and freedom, while existing decentralized solutions often lack the simplicity or scalability needed for widespread adoption. Centralized systems dominate modern technology, imposing control over data, access, and development through single points of failure and intermediaries. These structures compromise privacy, resilience, innovation, and freedom, while existing decentralized solutions often lack the simplicity or scalability needed for widespread adoption.
The DeBros Network resolves these issues by establishing a peer-to-peer platform where nodes form a decentralized backbone for applications. Built on Go's performance and LibP2P's proven networking stack, it empowers a global community of developers and users to collaborate as equals, delivering scalable, privacy-first solutions without centralized oversight. The DeBros Network resolves these issues by establishing a peer-to-peer platform where nodes form a decentralized backbone for applications. Built on LibP2P's proven networking stack and Rqlite as a database, it empowers a global community of developers and users to collaborate as equals, delivering scalable, privacy-first solutions without centralized oversight.
## 2. Problem Statement ## 2. Problem Statement

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"os/signal" "os/signal"
@ -15,6 +16,7 @@ import (
"git.debros.io/DeBros/network/pkg/logging" "git.debros.io/DeBros/network/pkg/logging"
"git.debros.io/DeBros/network/pkg/node" "git.debros.io/DeBros/network/pkg/node"
"go.uber.org/zap" "go.uber.org/zap"
"gopkg.in/yaml.v3"
) )
func setup_logger(component logging.Component) (logger *logging.ColoredLogger) { func setup_logger(component logging.Component) (logger *logging.ColoredLogger) {
@ -28,9 +30,10 @@ func setup_logger(component logging.Component) (logger *logging.ColoredLogger) {
return logger return logger
} }
func parse_and_return_network_flags() (dataDir, nodeID *string, p2pPort, rqlHTTP, rqlRaft *int, disableAnon *bool, rqlJoinAddr *string, advAddr *string, help *bool) { func parse_and_return_network_flags() (configPath *string, dataDir, nodeID *string, p2pPort, rqlHTTP, rqlRaft *int, disableAnon *bool, rqlJoinAddr *string, advAddr *string, help *bool) {
logger := setup_logger(logging.ComponentNode) logger := setup_logger(logging.ComponentNode)
configPath = flag.String("config", "", "Path to config YAML file (overrides defaults)")
dataDir = flag.String("data", "", "Data directory (auto-detected if not provided)") dataDir = flag.String("data", "", "Data directory (auto-detected if not provided)")
nodeID = flag.String("id", "", "Node identifier (for running multiple local nodes)") nodeID = flag.String("id", "", "Node identifier (for running multiple local nodes)")
p2pPort = flag.Int("p2p-port", 4001, "LibP2P listen port") p2pPort = flag.Int("p2p-port", 4001, "LibP2P listen port")
@ -38,15 +41,63 @@ func parse_and_return_network_flags() (dataDir, nodeID *string, p2pPort, rqlHTTP
rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port") rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port")
disableAnon = flag.Bool("disable-anonrc", false, "Disable Anyone proxy routing (defaults to enabled on 127.0.0.1:9050)") disableAnon = flag.Bool("disable-anonrc", false, "Disable Anyone proxy routing (defaults to enabled on 127.0.0.1:9050)")
rqlJoinAddr = flag.String("rqlite-join-address", "", "RQLite address to join (e.g., /ip4/)") rqlJoinAddr = flag.String("rqlite-join-address", "", "RQLite address to join (e.g., /ip4/)")
advAddr = flag.String("adv-addr", "127.0.0.1", "Default Addvertise address for rqlite and rafts") advAddr = flag.String("adv-addr", "127.0.0.1", "Default Advertise address for rqlite and rafts")
help = flag.Bool("help", false, "Show help") help = flag.Bool("help", false, "Show help")
flag.Parse() flag.Parse()
logger.Info("Successfully parsed all flags and arguments.") logger.Info("Successfully parsed all flags and arguments.")
if *configPath != "" {
cfg, err := LoadConfigFromYAML(*configPath)
if err != nil {
logger.Error("Failed to load config from YAML", zap.Error(err))
os.Exit(1)
}
logger.ComponentInfo(logging.ComponentNode, "Configuration loaded from YAML file", zap.String("path", *configPath))
// Instead of returning flag values, return config values
// For ListenAddresses, extract port from multiaddr string if possible, else use default
var p2pPortVal int
if len(cfg.Node.ListenAddresses) > 0 {
// Try to parse port from multiaddr string
var port int
_, err := fmt.Sscanf(cfg.Node.ListenAddresses[0], "/ip4/0.0.0.0/tcp/%d", &port)
if err == nil {
p2pPortVal = port
} else {
p2pPortVal = 4001
}
} else {
p2pPortVal = 4001
}
return configPath,
&cfg.Node.DataDir,
&cfg.Node.ID,
&p2pPortVal,
&cfg.Database.RQLitePort,
&cfg.Database.RQLiteRaftPort,
&cfg.Node.DisableAnonRC,
&cfg.Database.RQLiteJoinAddress,
&cfg.Discovery.HttpAdvAddress,
help
}
return return
} }
// LoadConfigFromYAML loads a config from a YAML file
func LoadConfigFromYAML(path string) (*config.Config, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
var cfg config.Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("failed to unmarshal YAML: %w", err)
}
return &cfg, nil
}
func disable_anon_proxy(disableAnon *bool) bool { func disable_anon_proxy(disableAnon *bool) bool {
anyoneproxy.SetDisabled(*disableAnon) anyoneproxy.SetDisabled(*disableAnon)
logger := setup_logger(logging.ComponentAnyone) logger := setup_logger(logging.ComponentAnyone)
@ -152,7 +203,7 @@ func load_args_into_config(cfg *config.Config, p2pPort, rqlHTTP, rqlRaft *int, r
func main() { func main() {
logger := setup_logger(logging.ComponentNode) logger := setup_logger(logging.ComponentNode)
dataDir, nodeID, p2pPort, rqlHTTP, rqlRaft, disableAnon, rqlJoinAddr, advAddr, help := parse_and_return_network_flags() _, dataDir, nodeID, p2pPort, rqlHTTP, rqlRaft, disableAnon, rqlJoinAddr, advAddr, help := parse_and_return_network_flags()
disable_anon_proxy(disableAnon) disable_anon_proxy(disableAnon)
check_if_should_open_help(help) check_if_should_open_help(help)

1
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/rqlite/gorqlite v0.0.0-20250609141355-ac86a4a1c9a8 github.com/rqlite/gorqlite v0.0.0-20250609141355-ac86a4a1c9a8
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/net v0.42.0 golang.org/x/net v0.42.0
gopkg.in/yaml.v3 v3.0.1
) )
require ( require (

View File

@ -22,9 +22,7 @@ type NodeConfig struct {
ListenAddresses []string `yaml:"listen_addresses"` // LibP2P listen addresses ListenAddresses []string `yaml:"listen_addresses"` // LibP2P listen addresses
DataDir string `yaml:"data_dir"` // Data directory DataDir string `yaml:"data_dir"` // Data directory
MaxConnections int `yaml:"max_connections"` // Maximum peer connections MaxConnections int `yaml:"max_connections"` // Maximum peer connections
DisableAnonRC bool `yaml:"disable_anon_rc"` // Disable Anyone proxy/SOCKS5
// Bootstrap configuration (only for bootstrap nodes)
IsBootstrap bool `yaml:"is_bootstrap"`
} }
// DatabaseConfig contains database-related configuration // DatabaseConfig contains database-related configuration
@ -97,7 +95,6 @@ func DefaultConfig() *Config {
}, },
DataDir: "./data", DataDir: "./data",
MaxConnections: 50, MaxConnections: 50,
IsBootstrap: false,
}, },
Database: DatabaseConfig{ Database: DatabaseConfig{
DataDir: "./data/db", DataDir: "./data/db",