Merge branch 'main' into nightly

This commit is contained in:
anonpenguin 2025-10-25 13:05:00 +03:00 committed by GitHub
commit 5939cf413e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 573 additions and 348 deletions

2
.gitignore vendored
View File

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

View File

@ -8,14 +8,38 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant
### Added ### Added
- One-command `make dev` target to start full development stack (bootstrap + node2 + node3 + gateway in background)
- New `network-cli config init` (no --type) generates complete development stack with all configs and identities
- Full stack initialization with auto-generated peer identities for bootstrap and all nodes
- Explicit control over LibP2P listen addresses for better localhost/development support
- Production/development mode detection for NAT services (disabled for localhost, enabled for production)
- Process management with .dev/pids directory for background process tracking
- Centralized logging to ~/.debros/logs/ for all network services
### Changed ### Changed
- Simplified Makefile: removed legacy dev commands, replaced with unified `make dev` target
- Updated README with clearer getting started instructions (single `make dev` command)
- Simplified `network-cli config init` behavior: defaults to generating full stack instead of single node
- `network-cli config init` now handles bootstrap peer discovery and join addresses automatically
- LibP2P configuration: removed always-on NAT services for development environments
- Code formatting in pkg/node/node.go (indentation fixes in bootstrapPeerSource)
### Deprecated ### Deprecated
### Removed ### Removed
- Removed legacy Makefile targets: run-example, show-bootstrap, run-cli, cli-health, cli-peers, cli-status, cli-storage-test, cli-pubsub-test
- Removed verbose dev-setup, dev-cluster, and old dev workflow targets
### Fixed ### Fixed
- Fixed indentation in bootstrapPeerSource function for consistency
- Fixed gateway.yaml generation with correct YAML indentation for bootstrap_peers
- Fixed script for running and added gateway running as well
### Security
## [0.51.6] - 2025-10-24 ## [0.51.6] - 2025-10-24
### Added ### Added

145
Makefile
View File

@ -21,7 +21,7 @@ test-e2e:
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports .PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports
VERSION := 0.51.6-beta VERSION := 0.51.7-beta
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)' LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)'
@ -77,110 +77,45 @@ run-gateway:
@echo "Generate it with: network-cli config init --type gateway" @echo "Generate it with: network-cli config init --type gateway"
go run ./cmd/gateway go run ./cmd/gateway
# Run basic usage example # One-command dev: Start bootstrap, node2, node3, and gateway in background
run-example: # Requires: configs already exist in ~/.debros
@echo "Running basic usage example..." dev: build
go run examples/basic_usage.go @echo "🚀 Starting development network stack..."
@mkdir -p .dev/pids
# Show how to run with flags @mkdir -p $$HOME/.debros/logs
show-bootstrap: @echo "Starting bootstrap node..."
@echo "Provide join address via flags, e.g.:" @nohup ./bin/node --config bootstrap.yaml > $$HOME/.debros/logs/bootstrap.log 2>&1 & echo $$! > .dev/pids/bootstrap.pid
@echo " make run-node2 JOINADDR=/ip4/127.0.0.1/tcp/5001 HTTP=5002 RAFT=7002 P2P=4002" @sleep 2
@echo "Starting node2..."
# Run network CLI @nohup ./bin/node --config node2.yaml > $$HOME/.debros/logs/node2.log 2>&1 & echo $$! > .dev/pids/node2.pid
run-cli: @sleep 1
@echo "Running network CLI help..." @echo "Starting node3..."
./bin/network-cli help @nohup ./bin/node --config node3.yaml > $$HOME/.debros/logs/node3.log 2>&1 & echo $$! > .dev/pids/node3.pid
@sleep 1
# Network CLI helper commands @echo "Starting gateway..."
cli-health: @nohup ./bin/gateway --config gateway.yaml > $$HOME/.debros/logs/gateway.log 2>&1 & echo $$! > .dev/pids/gateway.pid
@echo "Checking network health..."
./bin/network-cli health
cli-peers:
@echo "Listing network peers..."
./bin/network-cli peers
cli-status:
@echo "Getting network status..."
./bin/network-cli status
cli-storage-test:
@echo "Testing storage operations..."
@./bin/network-cli storage put test-key "Hello Network" || echo "Storage test requires running network"
@./bin/network-cli storage get test-key || echo "Storage test requires running network"
@./bin/network-cli storage list || echo "Storage test requires running network"
cli-pubsub-test:
@echo "Testing pub/sub operations..."
@./bin/network-cli pubsub publish test-topic "Hello World" || echo "PubSub test requires running network"
@./bin/network-cli pubsub topics || echo "PubSub test requires running network"
# Download dependencies
deps:
@echo "Downloading dependencies..."
go mod download
# Tidy dependencies
tidy:
@echo "Tidying dependencies..."
go mod tidy
# Format code
fmt:
@echo "Formatting code..."
go fmt ./...
# Vet code
vet:
@echo "Vetting code..."
go vet ./...
# Lint alias (lightweight for now)
lint: fmt vet
@echo "Linting complete (fmt + vet)"
# Clear common development ports
clear-ports:
@echo "Clearing common dev ports (4001/4002, 5001/5002, 7001/7002)..."
@chmod +x scripts/clear-ports.sh || true
@scripts/clear-ports.sh
# Development setup
dev-setup: deps
@echo "Setting up development environment..."
@mkdir -p data/bootstrap data/node data/node2 data/node3
@mkdir -p data/test-bootstrap data/test-node1 data/test-node2
@echo "Development setup complete!"
# Start development cluster (requires multiple terminals)
dev-cluster:
@echo "To start a development cluster with 3 nodes:"
@echo "" @echo ""
@echo "1. Generate config files in ~/.debros:" @echo "============================================================"
@echo " make build" @echo "✅ Development stack started!"
@echo " ./bin/network-cli config init --type bootstrap" @echo "============================================================"
@echo " ./bin/network-cli config init --type node --name node.yaml --bootstrap-peers '<bootstrap_peer_multiaddr>'"
@echo " ./bin/network-cli config init --type node --name node2.yaml --bootstrap-peers '<bootstrap_peer_multiaddr>'"
@echo "" @echo ""
@echo "2. Run in separate terminals:" @echo "Processes:"
@echo " Terminal 1: make run-node # Start bootstrap node (bootstrap.yaml)" @echo " Bootstrap: PID=$$(cat .dev/pids/bootstrap.pid)"
@echo " Terminal 2: make run-node2 # Start node 1 (node.yaml)" @echo " Node2: PID=$$(cat .dev/pids/node2.pid)"
@echo " Terminal 3: make run-node3 # Start node 2 (node2.yaml)" @echo " Node3: PID=$$(cat .dev/pids/node3.pid)"
@echo " Terminal 4: make run-gateway # Start gateway" @echo " Gateway: PID=$$(cat .dev/pids/gateway.pid)"
@echo "" @echo ""
@echo "3. Or run custom node with any config file:" @echo "Ports:"
@echo " go run ./cmd/node --config custom-node.yaml" @echo " Bootstrap P2P: 4001, HTTP: 5001, Raft: 7001"
@echo " Node2 P2P: 4002, HTTP: 5002, Raft: 7002"
@echo " Node3 P2P: 4003, HTTP: 5003, Raft: 7003"
@echo " Gateway: 6001"
@echo "" @echo ""
@echo "4. Test:" @echo "Press Ctrl+C to stop all processes"
@echo " make cli-health # Check network health" @echo "============================================================"
@echo " make cli-peers # List peers" @echo ""
@echo " make cli-storage-test # Test storage" @trap 'echo "Stopping all processes..."; kill $$(cat .dev/pids/*.pid) 2>/dev/null; rm -f .dev/pids/*.pid; exit 0' INT; \
@echo " make cli-pubsub-test # Test messaging" tail -f $$HOME/.debros/logs/bootstrap.log $$HOME/.debros/logs/node2.log $$HOME/.debros/logs/node3.log $$HOME/.debros/logs/gateway.log
# Full development workflow
dev: clean build test
@echo "Development workflow complete!"
# Help # Help
help: help:
@ -189,12 +124,14 @@ help:
@echo " clean - Clean build artifacts" @echo " clean - Clean build artifacts"
@echo " test - Run tests" @echo " test - Run tests"
@echo "" @echo ""
@echo "Development:"
@echo " dev - Start full dev stack (bootstrap + 2 nodes + gateway)"
@echo " Requires: configs in ~/.debros (run 'network-cli config init' first)"
@echo ""
@echo "Configuration (NEW):" @echo "Configuration (NEW):"
@echo " First, generate config files in ~/.debros with:" @echo " First, generate config files in ~/.debros with:"
@echo " make build # Build CLI first" @echo " make build # Build CLI first"
@echo " ./bin/network-cli config init --type bootstrap # Generate bootstrap config" @echo " ./bin/network-cli config init # Generate full stack"
@echo " ./bin/network-cli config init --type node --bootstrap-peers '<peer_multiaddr>'"
@echo " ./bin/network-cli config init --type gateway"
@echo "" @echo ""
@echo "Network Targets (requires config files in ~/.debros):" @echo "Network Targets (requires config files in ~/.debros):"
@echo " run-node - Start bootstrap node" @echo " run-node - Start bootstrap node"

126
README.md
View File

@ -174,23 +174,36 @@ cd network
make build make build
``` ```
### 3. Start a Bootstrap Node ### 3. Generate Configuration Files
```bash ```bash
make run-node # Generate all configs (bootstrap, node2, node3, gateway) with one command
# Or manually: ./bin/network-cli config init
go run ./cmd/node --config configs/node.yaml
``` ```
### 4. Start Additional Nodes This creates:
- `~/.debros/bootstrap.yaml` - Bootstrap node
- `~/.debros/node2.yaml` - Regular node 2
- `~/.debros/node3.yaml` - Regular node 3
- `~/.debros/gateway.yaml` - HTTP Gateway
Plus auto-generated identities for each node.
### 4. Start the Complete Network Stack
```bash ```bash
make run-node2 make dev
# Or manually:
go run ./cmd/node --config configs/node.yaml
``` ```
### 5. Test with CLI This starts:
- Bootstrap node (P2P: 4001, RQLite HTTP: 5001, Raft: 7001)
- Node 2 (P2P: 4002, RQLite HTTP: 5002, Raft: 7002)
- Node 3 (P2P: 4003, RQLite HTTP: 5003, Raft: 7003)
- Gateway (HTTP: 6001)
Logs stream to terminal. Press **Ctrl+C** to stop all processes.
### 5. Test with CLI (in another terminal)
```bash ```bash
./bin/network-cli health ./bin/network-cli health
@ -261,100 +274,103 @@ The system will **only** load config from `~/.debros/` and will error if require
Use the `network-cli config init` command to generate configuration files: Use the `network-cli config init` command to generate configuration files:
#### Generate a Node Config ### Generate Complete Stack (Recommended)
```bash
# Generate bootstrap, node2, node3, and gateway configs in one command
./bin/network-cli config init
# Force regenerate (overwrites existing configs)
./bin/network-cli config init --force
```
This is the **recommended way** to get started with a local development network.
### Generate Individual Configs (Advanced)
For custom setups or production deployments, you can generate individual configs:
#### Generate a Single Node Config
```bash ```bash
# Generate basic node config with bootstrap peers # Generate basic node config with bootstrap peers
network-cli config init --type node --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx,/ip4/127.0.0.1/tcp/4002/p2p/QmYyy" ./bin/network-cli config init --type node --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx"
# With custom ports # With custom ports
network-cli config init --type node --name node2.yaml --listen-port 4002 --rqlite-http-port 5002 --rqlite-raft-port 7002 --join localhost:5001 --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx" ./bin/network-cli config init --type node --name node2.yaml \
--listen-port 4002 --rqlite-http-port 5002 --rqlite-raft-port 7002 \
--join localhost:5001 --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx"
# Force overwrite existing config # Force overwrite existing config
network-cli config init --type node --force ./bin/network-cli config init --type node --force
``` ```
#### Generate a Bootstrap Node Config #### Generate a Bootstrap Node Config
```bash ```bash
# Generate bootstrap node (no join address required) # Generate bootstrap node (no join address required)
network-cli config init --type bootstrap ./bin/network-cli config init --type bootstrap
# With custom ports # With custom ports
network-cli config init --type bootstrap --listen-port 4001 --rqlite-http-port 5001 --rqlite-raft-port 7001 ./bin/network-cli config init --type bootstrap --listen-port 4001 --rqlite-http-port 5001 --rqlite-raft-port 7001
``` ```
#### Generate a Gateway Config #### Generate a Gateway Config
```bash ```bash
# Generate gateway config # Generate gateway config
network-cli config init --type gateway ./bin/network-cli config init --type gateway
# With bootstrap peers # With bootstrap peers
network-cli config init --type gateway --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx" ./bin/network-cli config init --type gateway --bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/QmXxx"
``` ```
### Running Multiple Nodes on the Same Machine ### Running the Network
You can run multiple nodes on a single machine by creating separate configuration files and using the `--config` flag: Once configs are generated, start the complete stack with:
#### Create Multiple Node Configs
```bash ```bash
# Node 1 make dev
./bin/network-cli config init --type node --name node1.yaml \
--listen-port 4001 --rqlite-http-port 5001 --rqlite-raft-port 7001 \
--bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_ID>"
# Node 2
./bin/network-cli config init --type node --name node2.yaml \
--listen-port 4002 --rqlite-http-port 5002 --rqlite-raft-port 7002 \
--join localhost:5001 \
--bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_ID>"
# Node 3
./bin/network-cli config init --type node --name node3.yaml \
--listen-port 4003 --rqlite-http-port 5003 --rqlite-raft-port 7003 \
--join localhost:5001 \
--bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_ID>"
``` ```
#### Run Multiple Nodes in Separate Terminals Or start individual components (in separate terminals):
```bash ```bash
# Terminal 1 - Bootstrap node # Terminal 1 - Bootstrap node
go run ./cmd/node --config bootstrap.yaml go run ./cmd/node --config bootstrap.yaml
# Terminal 2 - Node 1 # Terminal 2 - Node 2
go run ./cmd/node --config node1.yaml
# Terminal 3 - Node 2
go run ./cmd/node --config node2.yaml go run ./cmd/node --config node2.yaml
# Terminal 4 - Node 3 # Terminal 3 - Node 3
go run ./cmd/node --config node3.yaml go run ./cmd/node --config node3.yaml
# Terminal 4 - Gateway
go run ./cmd/gateway --config gateway.yaml
``` ```
#### Or Use Makefile Targets ### Running Multiple Nodes on the Same Machine
The default `make dev` creates a 3-node setup. For additional nodes, generate individual configs:
```bash ```bash
# Terminal 1 # Generate additional node configs with unique ports
make run-node # Runs: go run ./cmd/node --config bootstrap.yaml ./bin/network-cli config init --type node --name node4.yaml \
--listen-port 4004 --rqlite-http-port 5004 --rqlite-raft-port 7004 \
--join localhost:5001 \
--bootstrap-peers "/ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_ID>"
# Terminal 2 # Start the additional node
make run-node2 # Runs: go run ./cmd/node --config node.yaml go run ./cmd/node --config node4.yaml
# Terminal 3
make run-node3 # Runs: go run ./cmd/node --config node2.yaml
``` ```
#### Key Points for Multiple Nodes #### Key Points for Multiple Nodes
- **Each node needs unique ports**: P2P port, RQLite HTTP port, and RQLite Raft port must all be different - **Each node needs unique ports**: P2P port, RQLite HTTP port, and RQLite Raft port must all be different
- **Join address**: Non-bootstrap nodes need `rqlite_join_address` pointing to the bootstrap or an existing node - **Join address**: Non-bootstrap nodes need `rqlite_join_address` pointing to the bootstrap or an existing node (use Raft port)
- **Bootstrap peers**: All nodes need the bootstrap node's multiaddr in `discovery.bootstrap_peers` - **Bootstrap peers**: All nodes need the bootstrap node's multiaddr in `discovery.bootstrap_peers`
- **Config files**: Store all configs in `~/.debros/` with different filenames - **Config files**: Store all configs in `~/.debros/` with different filenames
- **--config flag**: Specify which config file to load (defaults to `node.yaml`) - **--config flag**: Specify which config file to load
⚠️ **Common Mistake - Same Ports:** ⚠️ **Common Mistake - Same Ports:**
If all nodes use the same ports (e.g., 5001, 7001), they will try to bind to the same addresses and fail to communicate. Verify each node has unique ports: If all nodes use the same ports (e.g., 5001, 7001), they will try to bind to the same addresses and fail to communicate. Verify each node has unique ports:
@ -365,11 +381,11 @@ grep "rqlite_port\|rqlite_raft_port" ~/.debros/bootstrap.yaml
# Should show: rqlite_port: 5001, rqlite_raft_port: 7001 # Should show: rqlite_port: 5001, rqlite_raft_port: 7001
# Node 2 # Node 2
grep "rqlite_port\|rqlite_raft_port" ~/.debros/node.yaml grep "rqlite_port\|rqlite_raft_port" ~/.debros/node2.yaml
# Should show: rqlite_port: 5002, rqlite_raft_port: 7002 # Should show: rqlite_port: 5002, rqlite_raft_port: 7002
# Node 3 # Node 3
grep "rqlite_port\|rqlite_raft_port" ~/.debros/node2.yaml grep "rqlite_port\|rqlite_raft_port" ~/.debros/node3.yaml
# Should show: rqlite_port: 5003, rqlite_raft_port: 7003 # Should show: rqlite_port: 5003, rqlite_raft_port: 7003
``` ```

View File

@ -15,6 +15,7 @@ import (
"github.com/DeBrosOfficial/network/pkg/auth" "github.com/DeBrosOfficial/network/pkg/auth"
"github.com/DeBrosOfficial/network/pkg/client" "github.com/DeBrosOfficial/network/pkg/client"
"github.com/DeBrosOfficial/network/pkg/config" "github.com/DeBrosOfficial/network/pkg/config"
"github.com/DeBrosOfficial/network/pkg/encryption"
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
) )
@ -607,30 +608,35 @@ func showConfigHelp() {
fmt.Printf("Config Management Commands\n\n") fmt.Printf("Config Management Commands\n\n")
fmt.Printf("Usage: network-cli config <subcommand> [options]\n\n") fmt.Printf("Usage: network-cli config <subcommand> [options]\n\n")
fmt.Printf("Subcommands:\n") fmt.Printf("Subcommands:\n")
fmt.Printf(" init - Generate configuration files in ~/.debros\n") fmt.Printf(" init - Generate full network stack in ~/.debros (bootstrap + 2 nodes + gateway)\n")
fmt.Printf(" validate --name <file> - Validate a config file\n\n") fmt.Printf(" validate --name <file> - Validate a config file\n\n")
fmt.Printf("Init Default Behavior (no --type):\n")
fmt.Printf(" Generates bootstrap.yaml, node2.yaml, node3.yaml, gateway.yaml with:\n")
fmt.Printf(" - Auto-generated identities for bootstrap, node2, node3\n")
fmt.Printf(" - Correct bootstrap_peers and join addresses\n")
fmt.Printf(" - Default ports: P2P 4001-4003, HTTP 5001-5003, Raft 7001-7003\n\n")
fmt.Printf("Init Options:\n") fmt.Printf("Init Options:\n")
fmt.Printf(" --type <type> - Config type: node, bootstrap, gateway (default: node)\n") fmt.Printf(" --type <type> - Single config type: node, bootstrap, gateway (skips stack generation)\n")
fmt.Printf(" --name <file> - Output filename (default: node.yaml)\n") fmt.Printf(" --name <file> - Output filename (default: depends on --type or 'stack' for full stack)\n")
fmt.Printf(" --force - Overwrite existing config/stack files\n\n")
fmt.Printf("Single Config Options (with --type):\n")
fmt.Printf(" --id <id> - Node ID for bootstrap peers\n") fmt.Printf(" --id <id> - Node ID for bootstrap peers\n")
fmt.Printf(" --listen-port <port> - LibP2P listen port (default: 4001)\n") fmt.Printf(" --listen-port <port> - LibP2P listen port (default: 4001)\n")
fmt.Printf(" --rqlite-http-port <port> - RQLite HTTP port (default: 5001)\n") fmt.Printf(" --rqlite-http-port <port> - RQLite HTTP port (default: 5001)\n")
fmt.Printf(" --rqlite-raft-port <port> - RQLite Raft port (default: 7001)\n") fmt.Printf(" --rqlite-raft-port <port> - RQLite Raft port (default: 7001)\n")
fmt.Printf(" --join <host:port> - RQLite address to join (required for non-bootstrap)\n") fmt.Printf(" --join <host:port> - RQLite address to join (required for non-bootstrap)\n")
fmt.Printf(" --bootstrap-peers <peers> - Comma-separated bootstrap peer multiaddrs\n") fmt.Printf(" --bootstrap-peers <peers> - Comma-separated bootstrap peer multiaddrs\n\n")
fmt.Printf(" --force - Overwrite existing config\n\n")
fmt.Printf("Examples:\n") fmt.Printf("Examples:\n")
fmt.Printf(" network-cli config init\n") fmt.Printf(" network-cli config init # Generate full stack\n")
fmt.Printf(" network-cli config init --type node --bootstrap-peers /ip4/127.0.0.1/tcp/4001/p2p/QmXxx,/ip4/127.0.0.1/tcp/4002/p2p/QmYyy\n") fmt.Printf(" network-cli config init --force # Overwrite existing stack\n")
fmt.Printf(" network-cli config init --type bootstrap\n") fmt.Printf(" network-cli config init --type bootstrap # Single bootstrap config (legacy)\n")
fmt.Printf(" network-cli config init --type gateway\n")
fmt.Printf(" network-cli config validate --name node.yaml\n") fmt.Printf(" network-cli config validate --name node.yaml\n")
} }
func handleConfigInit(args []string) { func handleConfigInit(args []string) {
// Parse flags // Parse flags
var ( var (
cfgType = "node" cfgType = ""
name = "" // Will be set based on type if not provided name = "" // Will be set based on type if not provided
id string id string
listenPort = 4001 listenPort = 4001
@ -694,6 +700,13 @@ func handleConfigInit(args []string) {
} }
} }
// If --type is not specified, generate full stack
if cfgType == "" {
initFullStack(force)
return
}
// Otherwise, continue with single-file generation
// Validate type // Validate type
if cfgType != "node" && cfgType != "bootstrap" && cfgType != "gateway" { if cfgType != "node" && cfgType != "bootstrap" && cfgType != "gateway" {
fmt.Fprintf(os.Stderr, "Invalid --type: %s (expected: node, bootstrap, or gateway)\n", cfgType) fmt.Fprintf(os.Stderr, "Invalid --type: %s (expected: node, bootstrap, or gateway)\n", cfgType)
@ -799,6 +812,192 @@ func handleConfigValidate(args []string) {
fmt.Printf("✅ Config is valid: %s\n", configPath) fmt.Printf("✅ Config is valid: %s\n", configPath)
} }
func initFullStack(force bool) {
fmt.Printf("🚀 Initializing full network stack...\n")
// Ensure ~/.debros directory exists
homeDir, err := os.UserHomeDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get home directory: %v\n", err)
os.Exit(1)
}
debrosDir := filepath.Join(homeDir, ".debros")
if err := os.MkdirAll(debrosDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Failed to create ~/.debros directory: %v\n", err)
os.Exit(1)
}
// Step 1: Generate bootstrap identity
bootstrapIdentityDir := filepath.Join(debrosDir, "bootstrap")
bootstrapIdentityPath := filepath.Join(bootstrapIdentityDir, "identity.key")
if !force {
if _, err := os.Stat(bootstrapIdentityPath); err == nil {
fmt.Fprintf(os.Stderr, "Bootstrap identity already exists at %s (use --force to overwrite)\n", bootstrapIdentityPath)
os.Exit(1)
}
}
bootstrapInfo, err := encryption.GenerateIdentity()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate bootstrap identity: %v\n", err)
os.Exit(1)
}
if err := os.MkdirAll(bootstrapIdentityDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Failed to create bootstrap data directory: %v\n", err)
os.Exit(1)
}
if err := encryption.SaveIdentity(bootstrapInfo, bootstrapIdentityPath); err != nil {
fmt.Fprintf(os.Stderr, "Failed to save bootstrap identity: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated bootstrap identity: %s (Peer ID: %s)\n", bootstrapIdentityPath, bootstrapInfo.PeerID.String())
// Construct bootstrap multiaddr
bootstrapMultiaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/4001/p2p/%s", bootstrapInfo.PeerID.String())
fmt.Printf(" Bootstrap multiaddr: %s\n", bootstrapMultiaddr)
// Step 2: Generate bootstrap.yaml
bootstrapName := "bootstrap.yaml"
bootstrapPath := filepath.Join(debrosDir, bootstrapName)
if !force {
if _, err := os.Stat(bootstrapPath); err == nil {
fmt.Fprintf(os.Stderr, "Bootstrap config already exists at %s (use --force to overwrite)\n", bootstrapPath)
os.Exit(1)
}
}
bootstrapContent := generateBootstrapConfig(bootstrapName, "", 4001, 5001, 7001)
if err := os.WriteFile(bootstrapPath, []byte(bootstrapContent), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write bootstrap config: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated bootstrap config: %s\n", bootstrapPath)
// Step 3: Generate node2 identity and config
node2IdentityDir := filepath.Join(debrosDir, "node2")
node2IdentityPath := filepath.Join(node2IdentityDir, "identity.key")
if !force {
if _, err := os.Stat(node2IdentityPath); err == nil {
fmt.Fprintf(os.Stderr, "Node2 identity already exists at %s (use --force to overwrite)\n", node2IdentityPath)
os.Exit(1)
}
}
node2Info, err := encryption.GenerateIdentity()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate node2 identity: %v\n", err)
os.Exit(1)
}
if err := os.MkdirAll(node2IdentityDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Failed to create node2 data directory: %v\n", err)
os.Exit(1)
}
if err := encryption.SaveIdentity(node2Info, node2IdentityPath); err != nil {
fmt.Fprintf(os.Stderr, "Failed to save node2 identity: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated node2 identity: %s (Peer ID: %s)\n", node2IdentityPath, node2Info.PeerID.String())
node2Name := "node2.yaml"
node2Path := filepath.Join(debrosDir, node2Name)
if !force {
if _, err := os.Stat(node2Path); err == nil {
fmt.Fprintf(os.Stderr, "Node2 config already exists at %s (use --force to overwrite)\n", node2Path)
os.Exit(1)
}
}
node2Content := generateNodeConfig(node2Name, "", 4002, 5002, 7002, "127.0.0.1:7001", bootstrapMultiaddr)
if err := os.WriteFile(node2Path, []byte(node2Content), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write node2 config: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated node2 config: %s\n", node2Path)
// Step 4: Generate node3 identity and config
node3IdentityDir := filepath.Join(debrosDir, "node3")
node3IdentityPath := filepath.Join(node3IdentityDir, "identity.key")
if !force {
if _, err := os.Stat(node3IdentityPath); err == nil {
fmt.Fprintf(os.Stderr, "Node3 identity already exists at %s (use --force to overwrite)\n", node3IdentityPath)
os.Exit(1)
}
}
node3Info, err := encryption.GenerateIdentity()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate node3 identity: %v\n", err)
os.Exit(1)
}
if err := os.MkdirAll(node3IdentityDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Failed to create node3 data directory: %v\n", err)
os.Exit(1)
}
if err := encryption.SaveIdentity(node3Info, node3IdentityPath); err != nil {
fmt.Fprintf(os.Stderr, "Failed to save node3 identity: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated node3 identity: %s (Peer ID: %s)\n", node3IdentityPath, node3Info.PeerID.String())
node3Name := "node3.yaml"
node3Path := filepath.Join(debrosDir, node3Name)
if !force {
if _, err := os.Stat(node3Path); err == nil {
fmt.Fprintf(os.Stderr, "Node3 config already exists at %s (use --force to overwrite)\n", node3Path)
os.Exit(1)
}
}
node3Content := generateNodeConfig(node3Name, "", 4003, 5003, 7003, "127.0.0.1:7001", bootstrapMultiaddr)
if err := os.WriteFile(node3Path, []byte(node3Content), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write node3 config: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated node3 config: %s\n", node3Path)
// Step 5: Generate gateway.yaml
gatewayName := "gateway.yaml"
gatewayPath := filepath.Join(debrosDir, gatewayName)
if !force {
if _, err := os.Stat(gatewayPath); err == nil {
fmt.Fprintf(os.Stderr, "Gateway config already exists at %s (use --force to overwrite)\n", gatewayPath)
os.Exit(1)
}
}
gatewayContent := generateGatewayConfig(bootstrapMultiaddr)
if err := os.WriteFile(gatewayPath, []byte(gatewayContent), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Failed to write gateway config: %v\n", err)
os.Exit(1)
}
fmt.Printf("✅ Generated gateway config: %s\n", gatewayPath)
// Print summary
fmt.Printf("\n" + strings.Repeat("=", 60) + "\n")
fmt.Printf("✅ Full network stack initialized successfully!\n")
fmt.Printf(strings.Repeat("=", 60) + "\n\n")
fmt.Printf("Configuration files created in: %s\n\n", debrosDir)
fmt.Printf("Bootstrap Node:\n")
fmt.Printf(" Config: %s\n", bootstrapPath)
fmt.Printf(" Peer ID: %s\n", bootstrapInfo.PeerID.String())
fmt.Printf(" Ports: P2P=4001, HTTP=5001, Raft=7001\n\n")
fmt.Printf("Node2:\n")
fmt.Printf(" Config: %s\n", node2Path)
fmt.Printf(" Ports: P2P=4002, HTTP=5002, Raft=7002\n")
fmt.Printf(" Join: 127.0.0.1:7001\n\n")
fmt.Printf("Node3:\n")
fmt.Printf(" Config: %s\n", node3Path)
fmt.Printf(" Ports: P2P=4003, HTTP=5003, Raft=7003\n")
fmt.Printf(" Join: 127.0.0.1:7001\n\n")
fmt.Printf("Gateway:\n")
fmt.Printf(" Config: %s\n\n", gatewayPath)
fmt.Printf("To start the network:\n")
fmt.Printf(" Terminal 1: ./bin/node --config bootstrap.yaml\n")
fmt.Printf(" Terminal 2: ./bin/node --config node2.yaml\n")
fmt.Printf(" Terminal 3: ./bin/node --config node3.yaml\n")
fmt.Printf(" Terminal 4: ./bin/gateway --config gateway.yaml\n")
fmt.Printf("\n" + strings.Repeat("=", 60) + "\n")
}
func generateNodeConfig(name, id string, listenPort, rqliteHTTPPort, rqliteRaftPort int, joinAddr, bootstrapPeers string) string { func generateNodeConfig(name, id string, listenPort, rqliteHTTPPort, rqliteRaftPort int, joinAddr, bootstrapPeers string) string {
nodeID := id nodeID := id
if nodeID == "" { if nodeID == "" {
@ -923,9 +1122,9 @@ func generateGatewayConfig(bootstrapPeers string) string {
var peersYAML strings.Builder var peersYAML strings.Builder
if len(peers) == 0 { if len(peers) == 0 {
peersYAML.WriteString(" bootstrap_peers: []") peersYAML.WriteString("bootstrap_peers: []")
} else { } else {
peersYAML.WriteString(" bootstrap_peers:\n") peersYAML.WriteString("bootstrap_peers:\n")
for _, p := range peers { for _, p := range peers {
fmt.Fprintf(&peersYAML, " - \"%s\"\n", p) fmt.Fprintf(&peersYAML, " - \"%s\"\n", p)
} }

View File

@ -250,12 +250,42 @@ func (n *Node) startLibP2P() error {
return fmt.Errorf("failed to load identity: %w", err) return fmt.Errorf("failed to load identity: %w", err)
} }
// Create LibP2P host with NAT traversal support // Create LibP2P host with explicit listen addresses
var opts []libp2p.Option var opts []libp2p.Option
opts = append(opts, opts = append(opts,
libp2p.Identity(identity), libp2p.Identity(identity),
libp2p.Security(noise.ID, noise.New), libp2p.Security(noise.ID, noise.New),
libp2p.DefaultMuxers, libp2p.DefaultMuxers,
)
// Add explicit listen addresses from config
if len(n.config.Node.ListenAddresses) > 0 {
listenAddrs := make([]multiaddr.Multiaddr, 0, len(n.config.Node.ListenAddresses))
for _, addr := range n.config.Node.ListenAddresses {
ma, err := multiaddr.NewMultiaddr(addr)
if err != nil {
return fmt.Errorf("invalid listen address %s: %w", addr, err)
}
listenAddrs = append(listenAddrs, ma)
}
opts = append(opts, libp2p.ListenAddrs(listenAddrs...))
n.logger.ComponentInfo(logging.ComponentLibP2P, "Configured listen addresses",
zap.Strings("addrs", n.config.Node.ListenAddresses))
}
// For localhost/development, disable NAT services
// For production, these would be enabled
isLocalhost := len(n.config.Node.ListenAddresses) > 0 &&
(strings.Contains(n.config.Node.ListenAddresses[0], "127.0.0.1") ||
strings.Contains(n.config.Node.ListenAddresses[0], "localhost"))
if isLocalhost {
n.logger.ComponentInfo(logging.ComponentLibP2P, "Localhost detected - disabling NAT services for local development")
// Don't add NAT/AutoRelay options for localhost
} else {
// Production: enable NAT traversal
n.logger.ComponentInfo(logging.ComponentLibP2P, "Production mode - enabling NAT services")
opts = append(opts,
libp2p.EnableNATService(), libp2p.EnableNATService(),
libp2p.EnableAutoNATv2(), libp2p.EnableAutoNATv2(),
libp2p.EnableRelay(), libp2p.EnableRelay(),
@ -264,6 +294,7 @@ func (n *Node) startLibP2P() error {
bootstrapPeerSource(n.config.Discovery.BootstrapPeers, n.logger.Logger), bootstrapPeerSource(n.config.Discovery.BootstrapPeers, n.logger.Logger),
), ),
) )
}
h, err := libp2p.New(opts...) h, err := libp2p.New(opts...)
if err != nil { if err != nil {

View File

@ -1,8 +1,8 @@
#!/bin/bash #!/bin/bash
# DeBros Network Node Installation Script (Modern Node-Only Setup) # DeBros Network Production Installation Script
# Installs, configures, and manages a DeBros network node with secure defaults. # Installs and configures a complete DeBros network node (bootstrap) with gateway.
# Supports update-in-place, systemd service, and CLI management. # Supports idempotent updates and secure systemd service management.
set -e set -e
trap 'echo -e "${RED}An error occurred. Installation aborted.${NOCOLOR}"; exit 1' ERR trap 'echo -e "${RED}An error occurred. Installation aborted.${NOCOLOR}"; exit 1' ERR
@ -25,6 +25,7 @@ GATEWAY_PORT="6001"
RAFT_PORT="7001" RAFT_PORT="7001"
UPDATE_MODE=false UPDATE_MODE=false
NON_INTERACTIVE=false NON_INTERACTIVE=false
DEBROS_USER="debros"
log() { echo -e "${CYAN}[$(date '+%Y-%m-%d %H:%M:%S')]${NOCOLOR} $1"; } log() { echo -e "${CYAN}[$(date '+%Y-%m-%d %H:%M:%S')]${NOCOLOR} $1"; }
error() { echo -e "${RED}[ERROR]${NOCOLOR} $1"; } error() { echo -e "${RED}[ERROR]${NOCOLOR} $1"; }
@ -115,7 +116,7 @@ check_existing_installation() {
remove_existing_installation() { remove_existing_installation() {
log "Removing existing installation..." log "Removing existing installation..."
for service in debros-node; do for service in debros-node debros-gateway; do
if systemctl list-unit-files | grep -q "$service.service"; then if systemctl list-unit-files | grep -q "$service.service"; then
log "Stopping $service service..." log "Stopping $service service..."
sudo systemctl stop $service.service 2>/dev/null || true sudo systemctl stop $service.service 2>/dev/null || true
@ -128,8 +129,8 @@ remove_existing_installation() {
sudo rm -rf "$INSTALL_DIR" sudo rm -rf "$INSTALL_DIR"
log "Removed installation directory" log "Removed installation directory"
fi fi
if id "debros" &>/dev/null; then if id "$DEBROS_USER" &>/dev/null; then
sudo userdel debros 2>/dev/null || true sudo userdel "$DEBROS_USER" 2>/dev/null || true
log "Removed debros user" log "Removed debros user"
fi fi
success "Existing installation removed" success "Existing installation removed"
@ -260,50 +261,24 @@ check_ports() {
success "All required ports are available" success "All required ports are available"
} }
configuration_wizard() {
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN} DeBros Network Configuration Wizard ${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}"
if [ "$NON_INTERACTIVE" = true ]; then
log "Non-interactive mode: using default configuration"
SOLANA_WALLET="11111111111111111111111111111111"
CONFIGURE_FIREWALL="yes"
log "Installation Directory: $INSTALL_DIR"
log "Firewall Configuration: $CONFIGURE_FIREWALL"
success "Configuration completed with defaults"
return 0
fi
log "${GREEN}Enter your Solana wallet address for node operator rewards:${NOCOLOR}"
while true; do
read -rp "Solana Wallet Address: " SOLANA_WALLET
if [[ -n "$SOLANA_WALLET" && ${#SOLANA_WALLET} -ge 32 ]]; then break; else error "Please enter a valid Solana wallet address"; fi
done
read -rp "Installation directory [default: $INSTALL_DIR]: " CUSTOM_INSTALL_DIR
if [[ -n "$CUSTOM_INSTALL_DIR" ]]; then INSTALL_DIR="$CUSTOM_INSTALL_DIR"; fi
read -rp "Configure firewall automatically? (yes/no) [default: yes]: " CONFIGURE_FIREWALL
CONFIGURE_FIREWALL="${CONFIGURE_FIREWALL:-yes}"
success "Configuration completed"
}
setup_directories() { setup_directories() {
log "Setting up directories and permissions..." log "Setting up directories and permissions..."
if ! id "debros" &>/dev/null; then if ! id "$DEBROS_USER" &>/dev/null; then
sudo useradd -r -s /bin/false -d "$INSTALL_DIR" debros sudo useradd -r -s /usr/sbin/nologin -d "$INSTALL_DIR" "$DEBROS_USER"
log "Created debros user" log "Created debros user"
else else
log "User 'debros' already exists" log "User 'debros' already exists"
fi fi
sudo mkdir -p "$INSTALL_DIR"/{bin,configs,keys,data,logs,src} sudo mkdir -p "$INSTALL_DIR"/{bin,src}
sudo mkdir -p "$INSTALL_DIR/keys/node" sudo chown -R "$DEBROS_USER:$DEBROS_USER" "$INSTALL_DIR"
sudo mkdir -p "$INSTALL_DIR/data/node"/{rqlite,storage}
sudo chown -R debros:debros "$INSTALL_DIR"
sudo chmod 755 "$INSTALL_DIR" sudo chmod 755 "$INSTALL_DIR"
sudo chmod 700 "$INSTALL_DIR/keys"
sudo chmod 700 "$INSTALL_DIR/keys/node"
sudo chmod 755 "$INSTALL_DIR/data"
sudo chmod 755 "$INSTALL_DIR/logs"
sudo chmod 755 "$INSTALL_DIR/configs"
sudo chmod 755 "$INSTALL_DIR/bin" sudo chmod 755 "$INSTALL_DIR/bin"
# Create ~/.debros for the debros user
DEBROS_HOME=$(sudo -u "$DEBROS_USER" sh -c 'echo ~')
sudo -u "$DEBROS_USER" mkdir -p "$DEBROS_HOME/.debros"
sudo chmod 0700 "$DEBROS_HOME/.debros"
success "Directory structure ready" success "Directory structure ready"
} }
@ -312,39 +287,20 @@ setup_source_code() {
if [ -d "$INSTALL_DIR/src/.git" ]; then if [ -d "$INSTALL_DIR/src/.git" ]; then
log "Updating existing repository..." log "Updating existing repository..."
cd "$INSTALL_DIR/src" cd "$INSTALL_DIR/src"
sudo -u debros git pull sudo -u "$DEBROS_USER" git pull
else else
log "Cloning repository..." log "Cloning repository..."
sudo -u debros git clone "$REPO_URL" "$INSTALL_DIR/src" sudo -u "$DEBROS_USER" git clone "$REPO_URL" "$INSTALL_DIR/src"
cd "$INSTALL_DIR/src" cd "$INSTALL_DIR/src"
fi fi
success "Source code ready" success "Source code ready"
} }
generate_identity() {
local identity_file="$INSTALL_DIR/keys/node/identity.key"
if [ -f "$identity_file" ]; then
if [ "$UPDATE_MODE" = true ]; then
log "Identity key already exists, keeping existing key"
success "Using existing node identity"
return 0
else
log "Identity key already exists, regenerating..."
sudo rm -f "$identity_file"
fi
fi
log "Generating node identity..."
cd "$INSTALL_DIR/src"
export PATH=$PATH:/usr/local/go/bin
sudo -u debros env "PATH=$PATH:/usr/local/go/bin" go run ./cmd/identity -output "$identity_file"
success "Node identity generated"
}
build_binaries() { build_binaries() {
log "Building DeBros Network binaries..." log "Building DeBros Network binaries..."
cd "$INSTALL_DIR/src" cd "$INSTALL_DIR/src"
export PATH=$PATH:/usr/local/go/bin export PATH=$PATH:/usr/local/go/bin
sudo -u debros env "PATH=$PATH:/usr/local/go/bin" make build
local services_were_running=() local services_were_running=()
if [ "$UPDATE_MODE" = true ]; then if [ "$UPDATE_MODE" = true ]; then
log "Update mode: checking for running services before binary update..." log "Update mode: checking for running services before binary update..."
@ -353,13 +309,22 @@ build_binaries() {
sudo systemctl stop debros-node.service sudo systemctl stop debros-node.service
services_were_running+=("debros-node") services_were_running+=("debros-node")
fi fi
if systemctl is-active --quiet debros-gateway.service 2>/dev/null; then
log "Stopping debros-gateway service to update binaries..."
sudo systemctl stop debros-gateway.service
services_were_running+=("debros-gateway")
fi
if [ ${#services_were_running[@]} -gt 0 ]; then if [ ${#services_were_running[@]} -gt 0 ]; then
log "Waiting for services to stop completely..." log "Waiting for services to stop completely..."
sleep 3 sleep 3
fi fi
fi fi
sudo -u "$DEBROS_USER" env "PATH=$PATH:/usr/local/go/bin" make build
sudo cp bin/* "$INSTALL_DIR/bin/" sudo cp bin/* "$INSTALL_DIR/bin/"
sudo chown debros:debros "$INSTALL_DIR/bin/"* sudo chown "$DEBROS_USER:$DEBROS_USER" "$INSTALL_DIR/bin/"*
sudo chmod 755 "$INSTALL_DIR/bin/"*
if [ "$UPDATE_MODE" = true ] && [ ${#services_were_running[@]} -gt 0 ]; then if [ "$UPDATE_MODE" = true ] && [ ${#services_were_running[@]} -gt 0 ]; then
log "Restarting previously running services..." log "Restarting previously running services..."
for service in "${services_were_running[@]}"; do for service in "${services_were_running[@]}"; do
@ -371,33 +336,26 @@ build_binaries() {
} }
generate_configs() { generate_configs() {
log "Generating configuration files..." log "Generating configuration files via network-cli..."
cat > /tmp/node.yaml << EOF DEBROS_HOME=$(sudo -u "$DEBROS_USER" sh -c 'echo ~')
node:
data_dir: "$INSTALL_DIR/data/node" # Generate bootstrap config
key_file: "$INSTALL_DIR/keys/node/identity.key" log "Generating bootstrap.yaml..."
listen_addresses: sudo -u "$DEBROS_USER" "$INSTALL_DIR/bin/network-cli" config init --type bootstrap --force
- "/ip4/0.0.0.0/tcp/$NODE_PORT"
solana_wallet: "$SOLANA_WALLET" # Generate gateway config
database: log "Generating gateway.yaml..."
rqlite_port: $RQLITE_PORT sudo -u "$DEBROS_USER" "$INSTALL_DIR/bin/network-cli" config init --type gateway --force
rqlite_raft_port: $RAFT_PORT
logging:
level: "info"
file: "$INSTALL_DIR/logs/node.log"
EOF
sudo mv /tmp/node.yaml "$INSTALL_DIR/configs/node.yaml"
sudo chown debros:debros "$INSTALL_DIR/configs/node.yaml"
success "Configuration files generated" success "Configuration files generated"
} }
configure_firewall() { configure_firewall() {
if [[ "$CONFIGURE_FIREWALL" == "yes" ]]; then
log "Configuring firewall rules..." log "Configuring firewall rules..."
if command -v ufw &> /dev/null; then if command -v ufw &> /dev/null; then
log "Adding UFW rules for DeBros Network ports..." log "Adding UFW rules for DeBros Network ports..."
for port in $NODE_PORT $RQLITE_PORT $RAFT_PORT $GATEWAY_PORT; do for port in $NODE_PORT $RQLITE_PORT $RAFT_PORT $GATEWAY_PORT; do
if ! sudo ufw allow $port; then if ! sudo ufw allow $port 2>/dev/null; then
error "Failed to allow port $port" error "Failed to allow port $port"
exit 1 exit 1
fi fi
@ -413,39 +371,41 @@ configure_firewall() {
else else
warning "UFW not found. Please configure firewall manually." warning "UFW not found. Please configure firewall manually."
log "Required ports to allow:" log "Required ports to allow:"
log " - Port $NODE_PORT (Node)" log " - Port $NODE_PORT (Node P2P)"
log " - Port $RQLITE_PORT (RQLite)" log " - Port $RQLITE_PORT (RQLite HTTP)"
log " - Port $RAFT_PORT (Raft)" log " - Port $RAFT_PORT (RQLite Raft)"
fi log " - Port $GATEWAY_PORT (Gateway)"
fi fi
} }
create_systemd_service() { create_systemd_services() {
local service_file="/etc/systemd/system/debros-node.service" log "Creating systemd service units..."
if [ -f "$service_file" ]; then
# Node service
local node_service_file="/etc/systemd/system/debros-node.service"
if [ -f "$node_service_file" ]; then
log "Cleaning up existing node service..." log "Cleaning up existing node service..."
sudo systemctl stop debros-node.service 2>/dev/null || true sudo systemctl stop debros-node.service 2>/dev/null || true
sudo systemctl disable debros-node.service 2>/dev/null || true sudo systemctl disable debros-node.service 2>/dev/null || true
sudo rm -f "$service_file" sudo rm -f "$node_service_file"
fi fi
sudo systemctl daemon-reload sudo systemctl daemon-reload
log "Creating new systemd service..." log "Creating new systemd service..."
local exec_start="$INSTALL_DIR/bin/node --config $INSTALL_DIR/configs/node.yaml" local exec_start="$INSTALL_DIR/bin/node --config $INSTALL_DIR/configs/node.yaml"
cat > /tmp/debros-node.service << EOF cat > /tmp/debros-node.service << EOF
[Unit] [Unit]
Description=DeBros Network Node Description=DeBros Network Node (Bootstrap)
After=network.target After=network-online.target
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
User=debros User=debros
Group=debros Group=debros
WorkingDirectory=$INSTALL_DIR WorkingDirectory=/opt/debros/src
Environment=ENVIRONMENT=production ExecStart=/opt/debros/bin/node --config bootstrap.yaml
ExecStart=$exec_start
Restart=always Restart=always
RestartSec=10 RestartSec=5
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal
SyslogIdentifier=debros-node SyslogIdentifier=debros-node
@ -454,26 +414,78 @@ NoNewPrivileges=yes
PrivateTmp=yes PrivateTmp=yes
ProtectSystem=strict ProtectSystem=strict
ProtectHome=yes ProtectHome=yes
ReadWritePaths=$INSTALL_DIR ReadWritePaths=/opt/debros
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
sudo mv /tmp/debros-node.service "$service_file" sudo mv /tmp/debros-node.service "$node_service_file"
# Gateway service
local gateway_service_file="/etc/systemd/system/debros-gateway.service"
if [ -f "$gateway_service_file" ]; then
log "Cleaning up existing gateway service..."
sudo systemctl stop debros-gateway.service 2>/dev/null || true
sudo systemctl disable debros-gateway.service 2>/dev/null || true
sudo rm -f "$gateway_service_file"
fi
log "Creating debros-gateway.service..."
cat > /tmp/debros-gateway.service << 'EOF'
[Unit]
Description=DeBros Gateway (HTTP/WebSocket)
After=debros-node.service
Wants=debros-node.service
[Service]
Type=simple
User=debros
Group=debros
WorkingDirectory=/opt/debros/src
ExecStart=/opt/debros/bin/gateway
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=debros-gateway
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/debros
[Install]
WantedBy=multi-user.target
EOF
sudo mv /tmp/debros-gateway.service "$gateway_service_file"
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable debros-node.service sudo systemctl enable debros-node.service
success "Systemd service ready" sudo systemctl enable debros-gateway.service
success "Systemd services ready"
} }
start_service() { start_services() {
log "Starting DeBros Network service..." log "Starting DeBros Network services..."
sudo systemctl start debros-node.service sudo systemctl start debros-node.service
sleep 3 sleep 3
if systemctl is-active --quiet debros-node.service; then if systemctl is-active --quiet debros-node.service; then
success "DeBros Network service started successfully" success "DeBros Node service started successfully"
else else
error "Failed to start DeBros Network service" error "Failed to start DeBros Node service"
log "Check logs with: sudo journalctl -u debros-node.service" log "Check logs with: sudo journalctl -u debros-node.service -f"
exit 1
fi
sleep 2
sudo systemctl start debros-gateway.service
sleep 2
if systemctl is-active --quiet debros-gateway.service; then
success "DeBros Gateway service started successfully"
else
error "Failed to start DeBros Gateway service"
log "Check logs with: sudo journalctl -u debros-gateway.service -f"
exit 1 exit 1
fi fi
} }
@ -501,14 +513,8 @@ main() {
if ! check_go_installation; then install_go; fi if ! check_go_installation; then install_go; fi
install_dependencies install_dependencies
install_rqlite install_rqlite
if [ "$UPDATE_MODE" != true ]; then configuration_wizard; else
log "Update mode: skipping configuration wizard"
SOLANA_WALLET="11111111111111111111111111111111"
CONFIGURE_FIREWALL="yes"
fi
setup_directories setup_directories
setup_source_code setup_source_code
generate_identity
build_binaries build_binaries
if [ "$UPDATE_MODE" != true ]; then if [ "$UPDATE_MODE" != true ]; then
generate_configs generate_configs
@ -516,8 +522,11 @@ main() {
else else
log "Update mode: keeping existing configuration" log "Update mode: keeping existing configuration"
fi fi
create_systemd_service create_systemd_services
start_service start_services
DEBROS_HOME=$(sudo -u "$DEBROS_USER" sh -c 'echo ~')
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
if [ "$UPDATE_MODE" = true ]; then if [ "$UPDATE_MODE" = true ]; then
log "${GREEN} Update Complete! ${NOCOLOR}" log "${GREEN} Update Complete! ${NOCOLOR}"
@ -526,21 +535,28 @@ main() {
fi fi
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Installation Directory:${NOCOLOR} ${CYAN}$INSTALL_DIR${NOCOLOR}" log "${GREEN}Installation Directory:${NOCOLOR} ${CYAN}$INSTALL_DIR${NOCOLOR}"
log "${GREEN}Configuration:${NOCOLOR} ${CYAN}$INSTALL_DIR/configs/node.yaml${NOCOLOR}" log "${GREEN}Config Directory:${NOCOLOR} ${CYAN}$DEBROS_HOME/.debros${NOCOLOR}"
log "${GREEN}Logs:${NOCOLOR} ${CYAN}$INSTALL_DIR/logs/node.log${NOCOLOR}"
log "${GREEN}LibP2P Port:${NOCOLOR} ${CYAN}$NODE_PORT${NOCOLOR}" log "${GREEN}LibP2P Port:${NOCOLOR} ${CYAN}$NODE_PORT${NOCOLOR}"
log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_PORT${NOCOLOR}" log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_PORT${NOCOLOR}"
log "${GREEN}Gateway Port:${NOCOLOR} ${CYAN}$GATEWAY_PORT${NOCOLOR}" log "${GREEN}Gateway Port:${NOCOLOR} ${CYAN}$GATEWAY_PORT${NOCOLOR}"
log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_PORT${NOCOLOR}" log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_PORT${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Management Commands:${NOCOLOR}" log "${GREEN}Service Management:${NOCOLOR}"
log "${CYAN} - sudo systemctl status debros-node${NOCOLOR} (Check status)" log "${CYAN} - sudo systemctl status debros-node${NOCOLOR} (Check node status)"
log "${CYAN} - sudo systemctl restart debros-node${NOCOLOR} (Restart service)" log "${CYAN} - sudo systemctl status debros-gateway${NOCOLOR} (Check gateway status)"
log "${CYAN} - sudo systemctl stop debros-node${NOCOLOR} (Stop service)" log "${CYAN} - sudo systemctl restart debros-node${NOCOLOR} (Restart node)"
log "${CYAN} - sudo systemctl start debros-node${NOCOLOR} (Start service)" log "${CYAN} - sudo systemctl restart debros-gateway${NOCOLOR} (Restart gateway)"
log "${CYAN} - sudo journalctl -u debros-node.service -f${NOCOLOR} (View logs)" log "${CYAN} - sudo systemctl stop debros-node${NOCOLOR} (Stop node)"
log "${CYAN} - $INSTALL_DIR/bin/network-cli${NOCOLOR} (Use CLI tools)" log "${CYAN} - sudo systemctl stop debros-gateway${NOCOLOR} (Stop gateway)"
log "${CYAN} - sudo journalctl -u debros-node.service -f${NOCOLOR} (View node logs)"
log "${CYAN} - sudo journalctl -u debros-gateway.service -f${NOCOLOR} (View gateway logs)"
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Verify Installation:${NOCOLOR}"
log "${CYAN} - Node health: curl http://127.0.0.1:5001/status${NOCOLOR}"
log "${CYAN} - Gateway health: curl http://127.0.0.1:6001/health${NOCOLOR}"
log "${CYAN} - Show bootstrap peer: cat $DEBROS_HOME/.debros/bootstrap/peer.info${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}"
if [ "$UPDATE_MODE" = true ]; then if [ "$UPDATE_MODE" = true ]; then
success "DeBros Network has been updated and is running!" success "DeBros Network has been updated and is running!"
else else