From b744f7f5130e915c29b7b09477cf3a4739793774 Mon Sep 17 00:00:00 2001 From: anonpenguin Date: Fri, 8 Aug 2025 20:09:28 +0300 Subject: [PATCH] refactor: standardize ports (LibP2P 4001, RQLite 5001/7001) and remove .env configuration --- .env.example | 14 -- AI_CONTEXT.md | 8 +- Makefile | 72 +++---- README.md | 293 ++++----------------------- clear-ports.sh | 48 +++++ cmd/cli/main.go | 18 +- cmd/node/main.go | 40 ++-- pkg/client/implementations.go | 10 +- pkg/constants/bootstrap.go | 156 ++------------ scripts/install-debros-network.sh | 6 +- scripts/setup-production-security.sh | 18 +- 11 files changed, 192 insertions(+), 491 deletions(-) delete mode 100644 .env.example create mode 100755 clear-ports.sh diff --git a/.env.example b/.env.example deleted file mode 100644 index 29f5680..0000000 --- a/.env.example +++ /dev/null @@ -1,14 +0,0 @@ -# Example Environment Configuration for Development -# Copy this to .env and modify as needed - -# Bootstrap peers for development (localhost) -BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j - -# Environment setting (development or production) -ENVIRONMENT=development - -# Note: In production, set ENVIRONMENT=production and the bootstrap.go will automatically -# use the production bootstrap peers defined in constants/bootstrap.go - -# For multiple bootstrap peers, separate with commas: -# BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/peer1,/ip4/127.0.0.1/tcp/4005/p2p/peer2 diff --git a/AI_CONTEXT.md b/AI_CONTEXT.md index feea449..e84be44 100644 --- a/AI_CONTEXT.md +++ b/AI_CONTEXT.md @@ -350,14 +350,14 @@ database: node: data_dir: "./data/node" listen_addresses: - - "/ip4/0.0.0.0/tcp/4002" + - "/ip4/0.0.0.0/tcp/4001" discovery: bootstrap_peers: - "/ip4/127.0.0.1/tcp/4001/p2p/{BOOTSTRAP_PEER_ID}" discovery_interval: "10s" database: - rqlite_port: 5002 - rqlite_raft_port: 7002 + rqlite_port: 5001 + rqlite_raft_port: 7001 rqlite_join_address: "http://localhost:5001" ``` @@ -452,7 +452,7 @@ for _, peer := range peers { } // Connect to specific peer -err := client.Network().ConnectToPeer(ctx, "/ip4/192.168.1.100/tcp/4002/p2p/{PEER_ID}") +err := client.Network().ConnectToPeer(ctx, "/ip4/192.168.1.100/tcp/4001/p2p/{PEER_ID}") ``` ## Troubleshooting diff --git a/Makefile b/Makefile index 1c2ff62..95e84de 100644 --- a/Makefile +++ b/Makefile @@ -23,40 +23,29 @@ test: @echo "Running tests..." go test -v ./... -# Run node (auto-detects if bootstrap or regular based on configuration) +# Run bootstrap node explicitly run-node: - @echo "Starting network node..." - go run cmd/node/main.go -data ./data/node + @echo "Starting BOOTSTRAP node (role=bootstrap)..." + go run cmd/node/main.go -role bootstrap -data ./data/bootstrap -# Run second node with different identity +# Run second node (regular) - requires BOOTSTRAP multiaddr +# Usage: make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ HTTP=5002 RAFT=7002 run-node2: - @echo "Starting second network node..." - go run cmd/node/main.go -id node2 + @echo "Starting REGULAR node2 (role=node)..." + @if [ -z "$(BOOTSTRAP)" ]; then echo "ERROR: Provide BOOTSTRAP multiaddr: make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ [HTTP=5002 RAFT=7002]"; exit 1; fi + go run cmd/node/main.go -role node -id node2 -data ./data/node2 -bootstrap $(BOOTSTRAP) -rqlite-http-port ${HTTP-5002} -rqlite-raft-port ${RAFT-7002} -# Run third node with different identity +# Run third node (regular) - requires BOOTSTRAP multiaddr +# Usage: make run-node3 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ HTTP=5003 RAFT=7003 run-node3: - @echo "Starting third network node..." - go run cmd/node/main.go -id node3 + @echo "Starting REGULAR node3 (role=node)..." + @if [ -z "$(BOOTSTRAP)" ]; then echo "ERROR: Provide BOOTSTRAP multiaddr: make run-node3 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ [HTTP=5003 RAFT=7003]"; exit 1; fi + go run cmd/node/main.go -role node -id node3 -data ./data/node3 -bootstrap $(BOOTSTRAP) -rqlite-http-port ${HTTP-5003} -rqlite-raft-port ${RAFT-7003} -# Show current bootstrap configuration +# Show how to run with flags show-bootstrap: - @echo "Current bootstrap configuration from .env:" - @cat .env 2>/dev/null || echo "No .env file found - using defaults" - -# Run example -run-example: - @echo "Running basic usage example..." - go run examples/basic_usage.go - -# Build Anchat -build-anchat: - @echo "Building Anchat..." - cd anchat && go build -o bin/anchat cmd/cli/main.go - -# Run Anchat demo -run-anchat: - @echo "Starting Anchat demo..." - cd anchat && go run cmd/cli/main.go demo_user + @echo "Provide bootstrap via flags, e.g.:" + @echo " make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ HTTP=5002 RAFT=7002" # Run network CLI run-cli: @@ -112,7 +101,6 @@ dev-setup: deps @echo "Setting up development environment..." @mkdir -p data/bootstrap data/node data/node-node2 data/node-node3 @mkdir -p data/test-bootstrap data/test-node1 data/test-node2 - @mkdir -p anchat/bin @echo "Development setup complete!" # Multi-node testing @@ -142,35 +130,31 @@ test-consensus: build # Start development cluster (requires multiple terminals) dev-cluster: @echo "To start a development cluster, run these commands in separate terminals:" - @echo "1. make run-node # Start first node (auto-detects as bootstrap in dev)" - @echo "2. make run-node2 # Start second node with different identity" - @echo "3. make run-node3 # Start third node with different identity" + @echo "1. make run-node # Start bootstrap node" + @echo "2. make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ HTTP=5002 RAFT=7002" + @echo "3. make run-node3 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/ HTTP=5003 RAFT=7003" @echo "4. make run-example # Test basic functionality" - @echo "5. make run-anchat # Start messaging app" - @echo "6. make show-bootstrap # Check bootstrap configuration" - @echo "7. make cli-health # Check network health" - @echo "8. make cli-peers # List peers" - @echo "9. make cli-storage-test # Test storage" - @echo "10. make cli-pubsub-test # Test messaging" + @echo "5. make cli-health # Check network health" + @echo "6. make cli-peers # List peers" + @echo "7. make cli-storage-test # Test storage" + @echo "8. make cli-pubsub-test # Test messaging" # Full development workflow -dev: clean build build-anchat test +dev: clean build test @echo "Development workflow complete!" # Help help: @echo "Available targets:" @echo " build - Build all executables" - @echo " build-anchat - Build Anchat application" @echo " clean - Clean build artifacts" @echo " test - Run tests" - @echo " run-node - Start network node (auto-detects bootstrap vs regular)" - @echo " run-node2 - Start second node with different identity" - @echo " run-node3 - Start third node with different identity" + @echo " run-node - Start bootstrap node (role=bootstrap)" + @echo " run-node2 - Start second node (role=node). Provide BOOTSTRAP, optional HTTP/RAFT" + @echo " run-node3 - Start third node (role=node). Provide BOOTSTRAP, optional HTTP/RAFT" @echo " run-example - Run usage example" - @echo " run-anchat - Run Anchat demo" @echo " run-cli - Run network CLI help" - @echo " show-bootstrap - Show current bootstrap configuration" + @echo " show-bootstrap - Show example bootstrap usage with flags" @echo " cli-health - Check network health" @echo " cli-peers - List network peers" @echo " cli-status - Get network status" diff --git a/README.md b/README.md index 3460aa5..bcd1113 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ A distributed peer-to-peer network built with Go and LibP2P, providing decentral - [3. Build the Project](#3-build-the-project) - [4. Start the Network](#4-start-the-network) - [5. Test with CLI](#5-test-with-cli) - - [6. Test Anchat Messaging](#6-test-anchat-messaging) - [Deployment](#deployment) - [Production Installation Script](#production-installation-script) - [One-Command Installation](#one-command-installation) @@ -51,11 +50,6 @@ A distributed peer-to-peer network built with Go and LibP2P, providing decentral - [Environment Setup](#environment-setup) - [Configuration System](#configuration-system) - [Client Library Usage](#client-library-usage) -- [Anchat - Decentralized Messaging Application](#anchat---decentralized-messaging-application) - - [Features](#features-1) - - [Quick Start with Anchat](#quick-start-with-anchat) - - [Anchat Commands](#anchat-commands) - - [Anchat Configuration](#anchat-configuration) - [Troubleshooting](#troubleshooting) - [Common Issues](#common-issues) - [Debug Commands](#debug-commands) @@ -165,11 +159,8 @@ Ensure these ports are available or configure firewall rules accordingly. ```bash # Clone the repository -git clone https://git.debros.io/DeBros/network-cluster.git -cd network-cluster - -# Copy environment configuration -cp .env.example .env +git clone https://git.debros.io/DeBros/network.git +cd network ``` ### 2. Generate Bootstrap Identity (Development Only) @@ -180,35 +171,18 @@ For development, you need to generate a consistent bootstrap peer identity: # Generate bootstrap peer identity go run scripts/generate-bootstrap-identity.go -# This will create data/bootstrap/identity.key and show the peer ID -# Copy the peer ID and update your .env files +# This will create data/bootstrap/identity.key and show the peer ID (and multiaddr) +# Save the printed peer ID to use with the -bootstrap flag ``` -**Important:** After generating the bootstrap identity, update both `.env` files: - -```bash -# Update main .env file -nano .env -# Update BOOTSTRAP_PEERS with the generated peer ID - -# Update Anchat .env file -nano anchat/.env -# Update BOOTSTRAP_PEERS with the same peer ID -``` +**Important:** After generating the bootstrap identity, copy the printed multiaddr +or peer ID for use with the `-bootstrap` flag when starting regular nodes. ### 3. Build the Project ```bash # Build all network executables make build - -# Build Anchat application -cd anchat -make build -cd .. - -# Or build everything at once -make build && make build-anchat ``` ### 4. Start the Network @@ -216,24 +190,33 @@ make build && make build-anchat **Terminal 1 - Bootstrap Node:** ```bash -make run-node -# This automatically detects and starts as bootstrap node on port 4001 -# if the local machine matches bootstrap peer configuration +# Start an explicit bootstrap node (LibP2P 4001, RQLite 5001/7001) +go run cmd/node/main.go -role bootstrap -data ./data/bootstrap ``` **Terminal 2 - Regular Node:** ```bash -make run-node -# This automatically connects to bootstrap peers from .env -# No need to specify bootstrap manually anymore! +# Replace with the ID printed by the identity generator +go run cmd/node/main.go \ + -role node \ + -id node2 \ + -data ./data/node2 \ + -bootstrap /ip4/127.0.0.1/tcp/4001/p2p/ \ + -rqlite-http-port 5002 \ + -rqlite-raft-port 7002 ``` **Terminal 3 - Another Node (optional):** ```bash -# For additional nodes, use different data directory -go run cmd/node/main.go -data ./data/node2 +go run cmd/node/main.go \ + -role node \ + -id node3 \ + -data ./data/node3 \ + -bootstrap /ip4/127.0.0.1/tcp/4001/p2p/ \ + -rqlite-http-port 5003 \ + -rqlite-raft-port 7003 ``` ### 5. Test with CLI @@ -253,18 +236,6 @@ make show-bootstrap ./bin/cli peers ``` -### 6. Test Anchat Messaging - -```bash -# Terminal 1 - First user -cd anchat -./bin/anchat - -# Terminal 2 - Second user -cd anchat -./bin/anchat -``` - ## Deployment ### Production Installation Script @@ -430,7 +401,7 @@ sudo cp -r /opt/debros/keys /backup/ ```bash # Check if ports are open -sudo netstat -tuln | grep -E "(4001|4002|5001|5002|7001|7002)" +sudo netstat -tuln | grep -E "(4001|5001|7001)" # Check service logs sudo journalctl -u debros-node.service --since "1 hour ago" @@ -448,81 +419,19 @@ ps aux | grep debros For more advanced configuration options and development setup, see the sections below. -## Environment Configuration +## Configuration -### Bootstrap Peers Configuration +### Bootstrap and Ports (via flags) -The network uses `.env` files to configure bootstrap peers automatically. This eliminates the need to manually specify bootstrap peer addresses when starting nodes. +- **Bootstrap node**: `-role bootstrap` +- **Regular node**: `-role node -bootstrap ` +- **RQLite ports**: `-rqlite-http-port` (default 5001), `-rqlite-raft-port` (default 7001) -#### Setup for Development - -1. **Copy example configuration:** - - ```bash - cp .env.example .env - cp anchat/.env.example anchat/.env - ``` - -2. **Generate bootstrap identity:** - - ```bash - go run scripts/generate-bootstrap-identity.go - ``` - -3. **Update .env files with the generated peer ID:** - - ```bash - # Main network .env - BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/YOUR_GENERATED_PEER_ID - - # Anchat .env - BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/YOUR_GENERATED_PEER_ID - ``` - -#### Configuration Files - -**Main Network (.env):** - -```bash -# Bootstrap Node Configuration for Development -BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j -BOOTSTRAP_PORT=4001 -ENVIRONMENT=development -``` - -**Anchat Application (anchat/.env):** - -```bash -# Anchat Bootstrap Configuration -BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWN3AQHuxAzXfu98tiFYw7W3N2SyDwdxDRANXJp3ktVf8j -BOOTSTRAP_PORT=4001 -ENVIRONMENT=development -ANCHAT_LOG_LEVEL=info -ANCHAT_DATABASE_NAME=anchattestingdb1 -``` - -#### Multiple Bootstrap Peers - -For production or redundancy, you can specify multiple bootstrap peers: - -```bash -BOOTSTRAP_PEERS=/ip4/bootstrap1.example.com/tcp/4001/p2p/12D3KooWPeer1,/ip4/bootstrap2.example.com/tcp/4001/p2p/12D3KooWPeer2,/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWLocalPeer -``` - -#### Checking Configuration - -```bash -# View current bootstrap configuration -make show-bootstrap - -# Check which .env file is being used -cat .env -cat anchat/.env -``` +Examples are shown in Quick Start above for local multi-node on a single machine. ## CLI Commands -The CLI and nodes now automatically load bootstrap peers from `.env` files - no manual configuration needed! +The CLI can still accept `--bootstrap ` to override discovery when needed. ### Network Operations @@ -568,7 +477,7 @@ The CLI and nodes now automatically load bootstrap peers from `.env` files - no ### Project Structure ``` -network-cluster/ +network/ ├── cmd/ │ ├── bootstrap/ # Bootstrap node │ ├── node/ # Regular network node @@ -580,21 +489,9 @@ network-cluster/ │ ├── storage/ # Storage service │ ├── constants/ # Bootstrap configuration │ └── config/ # System configuration -├── anchat/ # Anchat messaging application -│ ├── cmd/cli/ # Anchat CLI -│ ├── pkg/ -│ │ ├── chat/ # Chat functionality -│ │ ├── crypto/ # Encryption -│ │ └── constants/ # Anchat bootstrap config -│ ├── .env # Anchat environment config -│ └── .env.example # Anchat config template -├── scripts/ -│ └── generate-bootstrap-identity.go # Bootstrap ID generator -├── .env # Main environment config -├── .env.example # Main config template +├── scripts/ # Helper scripts (install, security, tests) +├── scripts/ # Helper scripts (install, security, tests) ├── bin/ # Built executables -├── data/ # Runtime data directories -└── Makefile # Build and run commands ``` ### Building and Testing @@ -603,11 +500,6 @@ network-cluster/ # Build all network executables make build -# Build Anchat application -cd anchat && make build && cd .. -# or -make build-anchat - # Show current bootstrap configuration make show-bootstrap @@ -631,19 +523,17 @@ make dev ```bash # Copy environment templates cp .env.example .env - cp anchat/.env.example anchat/.env # Generate consistent bootstrap identity go run scripts/generate-bootstrap-identity.go - # Update both .env files with the generated peer ID + # Update .env files with the generated peer ID ``` 2. **Build Everything:** ```bash make build # Build network components - make build-anchat # Build Anchat application ``` 3. **Start Development Cluster:** @@ -658,9 +548,6 @@ make dev # Terminal 3: Test with CLI ./bin/cli health ./bin/cli peers - - # Terminal 4 & 5: Test Anchat - cd anchat && ./bin/anchat ``` ### Environment Setup @@ -689,7 +576,6 @@ make dev ```bash # Setup .env files cp .env.example .env - cp anchat/.env.example anchat/.env # Generate bootstrap identity go run scripts/generate-bootstrap-identity.go @@ -756,100 +642,6 @@ func main() { } ``` -## Anchat - Decentralized Messaging Application - -Anchat is a demonstration application built on the network that provides decentralized, encrypted messaging capabilities. - -### Features - -- **Decentralized Messaging**: No central servers, messages flow through the P2P network -- **Wallet-based Authentication**: Connect using Solana wallet addresses -- **Encrypted Communications**: End-to-end encryption for private messages -- **Room-based Chat**: Create and join chat rooms -- **Network Auto-discovery**: Automatically finds and connects to other Anchat users - -### Quick Start with Anchat - -1. **Setup Environment:** - - ```bash - # Ensure main network is configured - cp .env.example .env - cp anchat/.env.example anchat/.env - - # Generate bootstrap identity and update .env files - go run scripts/generate-bootstrap-identity.go - ``` - -2. **Build Anchat:** - - ```bash - cd anchat - make build - ``` - -3. **Start Network Infrastructure:** - - ```bash - # Terminal 1: Bootstrap node (auto-detected) - make run-node - - # Terminal 2: Regular node (optional but recommended) - make run-node - ``` - -4. **Start Anchat Clients:** - - ```bash - # Terminal 3: First user - cd anchat - ./bin/anchat - - # Terminal 4: Second user - cd anchat - ./bin/anchat - ``` - -### Anchat Commands - -```bash -# Room management -/list # List available rooms -/join # Join a room -/leave # Leave current room -/create [desc] # Create a new room - -# Messaging - # Send message to current room -/msg # Send private message -/me # Send action message - -# User management -/users # List users in current room -/nick # Change username -/who # Show your user info - -# System -/help # Show all commands -/debug # Show debug information -/quit # Exit Anchat -``` - -### Anchat Configuration - -Anchat uses its own bootstrap configuration in `anchat/.env`: - -```bash -# Anchat-specific environment variables -BOOTSTRAP_PEERS=/ip4/127.0.0.1/tcp/4001/p2p/YOUR_BOOTSTRAP_PEER_ID -BOOTSTRAP_PORT=4001 -ENVIRONMENT=development -ANCHAT_LOG_LEVEL=info -ANCHAT_DATABASE_NAME=anchattestingdb1 -``` - -The Anchat application also includes hardcoded fallback bootstrap peers in `anchat/pkg/constants/bootstrap.go` for reliability. - ## Troubleshooting ### Common Issues @@ -857,7 +649,7 @@ The Anchat application also includes hardcoded fallback bootstrap peers in `anch **Bootstrap peer not found / Peer ID mismatch:** - Generate a new bootstrap identity: `go run scripts/generate-bootstrap-identity.go` -- Update both `.env` and `anchat/.env` with the new peer ID +- Update `.env` with the new peer ID - Restart the bootstrap node: `make run-node` - Check configuration: `make show-bootstrap` @@ -875,26 +667,18 @@ The Anchat application also includes hardcoded fallback bootstrap peers in `anch - Verify RQLite is properly installed: `rqlited --version` - Check for port conflicts: `netstat -an | grep -E "(4001|5001|7001)"` -**Anchat clients can't discover each other:** - -- Ensure both clients use the same bootstrap peer ID in `anchat/.env` -- Verify the bootstrap node is running -- Check that both clients successfully connect to bootstrap -- Look for "peer id mismatch" errors in the logs - ### Debug Commands ```bash # Check current configuration make show-bootstrap cat .env -cat anchat/.env # Check running processes ps aux | grep -E "(bootstrap|node|rqlite)" # Check port usage -netstat -an | grep -E "(4001|4002|4003|5001|5002|5003|7001|7002|7003)" +netstat -an | grep -E "(4001|5001|7001)" # Check bootstrap peer info cat data/bootstrap/peer.info @@ -927,7 +711,6 @@ go run -c 'package main; import "fmt"; import "network/pkg/constants"; func main # Verify .env file syntax grep -E "^[A-Z_]+=.*" .env -grep -E "^[A-Z_]+=.*" anchat/.env ``` ### Logs and Data @@ -937,7 +720,7 @@ grep -E "^[A-Z_]+=.*" anchat/.env - RQLite data: `./data//rqlite/` - Peer info: `./data//peer.info` - Bootstrap identity: `./data/bootstrap/identity.key` -- Environment config: `./.env`, `./anchat/.env` +- Environment config: `./.env` ## License diff --git a/clear-ports.sh b/clear-ports.sh new file mode 100755 index 0000000..f246c23 --- /dev/null +++ b/clear-ports.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# clear-ports.sh +# Safely terminate any processes listening on specified TCP ports. +# Usage: +# ./clear-ports.sh # clears 4001, 5001, 7001 by default +# ./clear-ports.sh 4001 5001 7001 # clears the specified ports + +set -euo pipefail + +# Collect ports from args or use defaults +PORTS=("$@") +if [ ${#PORTS[@]} -eq 0 ]; then + PORTS=(4001 5001 7001) +fi + +echo "Gracefully terminating listeners on: ${PORTS[*]}" +for p in "${PORTS[@]}"; do + PIDS=$(lsof -t -n -P -iTCP:"$p" -sTCP:LISTEN 2>/dev/null || true) + if [ -n "$PIDS" ]; then + echo "Port $p -> PIDs: $PIDS (SIGTERM)" + # shellcheck disable=SC2086 + kill -TERM $PIDS 2>/dev/null || true + else + echo "Port $p -> no listeners" + fi +done + +sleep 1 + +echo "Force killing any remaining listeners..." +for p in "${PORTS[@]}"; do + PIDS=$(lsof -t -n -P -iTCP:"$p" -sTCP:LISTEN 2>/dev/null || true) + if [ -n "$PIDS" ]; then + echo "Port $p -> PIDs: $PIDS (SIGKILL)" + # shellcheck disable=SC2086 + kill -9 $PIDS 2>/dev/null || true + else + echo "Port $p -> none remaining" + fi +done + +echo "\nVerification (should be empty):" +for p in "${PORTS[@]}"; do + echo "--- Port $p ---" + lsof -n -P -iTCP:"$p" -sTCP:LISTEN 2>/dev/null || true + echo +done + diff --git a/cmd/cli/main.go b/cmd/cli/main.go index d05792e..f3cb7a1 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -10,10 +10,10 @@ import ( "strings" "time" - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/peer" "git.debros.io/DeBros/network/pkg/client" "git.debros.io/DeBros/network/pkg/constants" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" ) var ( @@ -362,7 +362,7 @@ func handlePeerID() { defer client.Disconnect() ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - + if status, err := client.Network().GetStatus(ctx); err == nil { if format == "json" { printJSON(map[string]string{"peer_id": status.NodeID}) @@ -372,7 +372,7 @@ func handlePeerID() { return } } - + // Fallback: try to extract from local identity files identityPaths := []string{ "/opt/debros/data/node/identity.key", @@ -381,7 +381,7 @@ func handlePeerID() { "./data/node/identity.key", "./data/bootstrap/identity.key", } - + for _, path := range identityPaths { if peerID := extractPeerIDFromFile(path); peerID != "" { if format == "json" { @@ -393,7 +393,7 @@ func handlePeerID() { return } } - + // Check peer.info files as last resort peerInfoPaths := []string{ "/opt/debros/data/node/peer.info", @@ -401,7 +401,7 @@ func handlePeerID() { "./data/node/peer.info", "./data/bootstrap/peer.info", } - + for _, path := range peerInfoPaths { if data, err := os.ReadFile(path); err == nil { multiaddr := strings.TrimSpace(string(data)) @@ -416,14 +416,14 @@ func handlePeerID() { } } } - + fmt.Fprintf(os.Stderr, "❌ Could not find peer ID. Make sure the node is running or identity files exist.\n") os.Exit(1) } func createClient() (client.NetworkClient, error) { var bootstrapPeers []string - + if useProduction { // Set environment to production to trigger production bootstrap peers os.Setenv("ENVIRONMENT", "production") diff --git a/cmd/node/main.go b/cmd/node/main.go index ca1ca38..8da0843 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -23,6 +23,9 @@ func main() { dataDir = flag.String("data", "", "Data directory (auto-detected if not provided)") nodeID = flag.String("id", "", "Node identifier (for running multiple local nodes)") bootstrap = flag.String("bootstrap", "", "Bootstrap peer address (for manual override)") + role = flag.String("role", "auto", "Node role: auto|bootstrap|node (auto detects based on config)") + rqlHTTP = flag.Int("rqlite-http-port", 5001, "RQLite HTTP API port") + rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port") help = flag.Bool("help", false, "Show help") ) flag.Parse() @@ -32,8 +35,17 @@ func main() { return } - // Auto-detect if this is a bootstrap node based on configuration - isBootstrap := isBootstrapNode() + // Determine node role + var isBootstrap bool + switch strings.ToLower(*role) { + case "bootstrap": + isBootstrap = true + case "node": + isBootstrap = false + default: + // Auto-detect if this is a bootstrap node based on configuration + isBootstrap = isBootstrapNode() + } // Set default data directory if not provided if *dataDir == "" { @@ -48,8 +60,8 @@ func main() { } } - // LibP2P uses port 4000, RQLite uses 4001 - port := 4000 + // LibP2P uses port 4001, RQLite uses 5001 (HTTP) and 7001 (Raft) + port := 4001 // Create logger with appropriate component type var logger *logging.StandardLogger @@ -80,9 +92,9 @@ func main() { fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", port), } - // All nodes use the same RQLite port (4001) to join the same cluster - cfg.Database.RQLitePort = 4001 - cfg.Database.RQLiteRaftPort = 4002 + // RQLite ports (overridable for local multi-node on one host) + cfg.Database.RQLitePort = *rqlHTTP + cfg.Database.RQLiteRaftPort = *rqlRaft if isBootstrap { // Check if this is the primary bootstrap node (first in list) or secondary @@ -98,11 +110,11 @@ func main() { } } } - + if isSecondaryBootstrap { // Secondary bootstrap nodes join the primary bootstrap primaryBootstrapHost := parseHostFromMultiaddr(bootstrapPeers[0]) - cfg.Database.RQLiteJoinAddress = fmt.Sprintf("http://%s:4001", primaryBootstrapHost) + cfg.Database.RQLiteJoinAddress = fmt.Sprintf("http://%s:%d", primaryBootstrapHost, *rqlHTTP) logger.Printf("Secondary bootstrap node - joining primary bootstrap at: %s", cfg.Database.RQLiteJoinAddress) } else { // Primary bootstrap node doesn't join anyone - it starts the cluster @@ -118,11 +130,11 @@ func main() { // Extract IP from bootstrap peer for RQLite join bootstrapHost := parseHostFromMultiaddr(*bootstrap) if bootstrapHost != "" { - rqliteJoinAddr = fmt.Sprintf("http://%s:4001", bootstrapHost) + rqliteJoinAddr = fmt.Sprintf("http://%s:%d", bootstrapHost, *rqlHTTP) logger.Printf("Using extracted bootstrap host %s for RQLite join", bootstrapHost) } else { logger.Printf("Warning: Could not extract host from bootstrap peer %s, using localhost fallback", *bootstrap) - rqliteJoinAddr = "http://localhost:4001" // Use localhost fallback instead + rqliteJoinAddr = fmt.Sprintf("http://localhost:%d", *rqlHTTP) // Use localhost fallback instead } logger.Printf("Using command line bootstrap peer: %s", *bootstrap) } else { @@ -133,18 +145,18 @@ func main() { // Use the first bootstrap peer for RQLite join bootstrapHost := parseHostFromMultiaddr(bootstrapPeers[0]) if bootstrapHost != "" { - rqliteJoinAddr = fmt.Sprintf("http://%s:4001", bootstrapHost) + rqliteJoinAddr = fmt.Sprintf("http://%s:5001", bootstrapHost) logger.Printf("Using extracted bootstrap host %s for RQLite join", bootstrapHost) } else { logger.Printf("Warning: Could not extract host from bootstrap peer %s", bootstrapPeers[0]) // Try primary production server as fallback - rqliteJoinAddr = "http://localhost:4001" + rqliteJoinAddr = "http://localhost:5001" } logger.Printf("Using environment bootstrap peers: %v", bootstrapPeers) } else { logger.Printf("Warning: No bootstrap peers configured") // Default to localhost when no peers configured - rqliteJoinAddr = "http://localhost:4001" + rqliteJoinAddr = "http://localhost:5001" logger.Printf("Using localhost fallback for RQLite join") } diff --git a/pkg/client/implementations.go b/pkg/client/implementations.go index 3825b0f..59a423c 100644 --- a/pkg/client/implementations.go +++ b/pkg/client/implementations.go @@ -197,7 +197,7 @@ func (d *DatabaseClientImpl) connectToAvailableNode() (*gorqlite.Connection, err return nil, fmt.Errorf("failed to connect to any RQLite instance. Last error: %w", lastErr) } -// getRQLiteNodes returns a list of RQLite node URLs using the peer IPs/hostnames from bootstrap.go, always on port 4001 +// getRQLiteNodes returns a list of RQLite node URLs using the peer IPs/hostnames from bootstrap.go, always on port 5001 func (d *DatabaseClientImpl) getRQLiteNodes() []string { // Use bootstrap peer addresses from constants // Import the constants package @@ -207,7 +207,7 @@ func (d *DatabaseClientImpl) getRQLiteNodes() []string { // Example multiaddr: /ip4/57.129.81.31/tcp/4001/p2p/12D3KooWQRK2duw5B5LXi8gA7HBBFiCsLvwyph2ZU9VBmvbE1Nei parts := strings.Split(addr, "/") var host string - var port string = "4001" // always use 4001 + var port string = "5001" // always use RQLite HTTP 5001 for i := 0; i < len(parts); i++ { if parts[i] == "ip4" || parts[i] == "ip6" { host = parts[i+1] @@ -215,15 +215,15 @@ func (d *DatabaseClientImpl) getRQLiteNodes() []string { if parts[i] == "dns" || parts[i] == "dns4" || parts[i] == "dns6" { host = parts[i+1] } - // ignore tcp port in multiaddr, always use 4001 + // ignore tcp port in multiaddr, always use 5001 for RQLite HTTP } if host != "" { nodes = append(nodes, "http://"+host+":"+port) } } - // If no peers found, fallback to localhost:4001 + // If no peers found, fallback to localhost:5001 if len(nodes) == 0 { - nodes = append(nodes, "http://localhost:4001") + nodes = append(nodes, "http://localhost:5001") } return nodes } diff --git a/pkg/constants/bootstrap.go b/pkg/constants/bootstrap.go index 15d9789..84b1ed3 100644 --- a/pkg/constants/bootstrap.go +++ b/pkg/constants/bootstrap.go @@ -2,11 +2,6 @@ package constants import ( "os" - "path/filepath" - "strconv" - "strings" - - "github.com/joho/godotenv" ) // Bootstrap node configuration @@ -19,109 +14,8 @@ var ( BootstrapAddresses []string // BootstrapPort is the default port for bootstrap nodes (LibP2P) - BootstrapPort int = 4000 -) + BootstrapPort int = 4001 -// Load environment variables and initialize bootstrap configuration -func init() { - loadEnvironmentConfig() -} - -// loadEnvironmentConfig loads bootstrap configuration from .env file -func loadEnvironmentConfig() { - // Try to load .env file from current directory and parent directories - envPaths := []string{ - ".env", - "../.env", - "../../.env", // For when running from anchat subdirectory - } - - var envLoaded bool - for _, path := range envPaths { - if _, err := os.Stat(path); err == nil { - if err := godotenv.Load(path); err == nil { - envLoaded = true - break - } - } - } - - if !envLoaded { - // Fallback to default values if no .env file found - setDefaultBootstrapConfig() - return - } - - // Load bootstrap peers from environment - if peersEnv := os.Getenv("BOOTSTRAP_PEERS"); peersEnv != "" { - // Split by comma and trim whitespace - peerAddrs := strings.Split(peersEnv, ",") - BootstrapAddresses = make([]string, 0, len(peerAddrs)) - BootstrapPeerIDs = make([]string, 0, len(peerAddrs)) - - for _, addr := range peerAddrs { - addr = strings.TrimSpace(addr) - if addr != "" { - BootstrapAddresses = append(BootstrapAddresses, addr) - - // Extract peer ID from multiaddr - if peerID := extractPeerIDFromMultiaddr(addr); peerID != "" { - BootstrapPeerIDs = append(BootstrapPeerIDs, peerID) - } - } - } - } - - // Load bootstrap port from environment - if portEnv := os.Getenv("BOOTSTRAP_PORT"); portEnv != "" { - if port, err := strconv.Atoi(portEnv); err == nil && port > 0 { - BootstrapPort = port - } - } - - // If no environment config found, use defaults - if len(BootstrapAddresses) == 0 { - setDefaultBootstrapConfig() - } -} - -// setDefaultBootstrapConfig sets default bootstrap configuration -func setDefaultBootstrapConfig() { - // Check if we're in production environment - if env := os.Getenv("ENVIRONMENT"); env == "production" { - // Production: only use live production peers - BootstrapPeerIDs = []string{ - "12D3KooWNxt9bNvqftdqXg98JcUHreGxedWSZRUbyqXJ6CW7GaD4", - "12D3KooWGbdnA22bN24X2gyY1o9jozwTBq9wbfvwtJ7G4XQ9JgFm", - } - BootstrapAddresses = []string{ - "/ip4/57.129.81.31/tcp/4000/p2p/12D3KooWNxt9bNvqftdqXg98JcUHreGxedWSZRUbyqXJ6CW7GaD4", - "/ip4/38.242.250.186/tcp/4000/p2p/12D3KooWGbdnA22bN24X2gyY1o9jozwTBq9wbfvwtJ7G4XQ9JgFm", - } - } else { - // Development: only use localhost bootstrap - BootstrapPeerIDs = []string{ - "12D3KooWBQAr9Lj9Z3918wBT523tJaRiPN6zRywAtttvPrwcZfJb", - } - BootstrapAddresses = []string{ - "/ip4/127.0.0.1/tcp/4000/p2p/12D3KooWBQAr9Lj9Z3918wBT523tJaRiPN6zRywAtttvPrwcZfJb", - } - } - BootstrapPort = 4000 -} - -// extractPeerIDFromMultiaddr extracts the peer ID from a multiaddr string -func extractPeerIDFromMultiaddr(multiaddr string) string { - // Look for /p2p/ followed by the peer ID - parts := strings.Split(multiaddr, "/p2p/") - if len(parts) >= 2 { - return parts[1] - } - return "" -} - -// Constants for backward compatibility -var ( // Primary bootstrap peer ID (first in the list) BootstrapPeerID string @@ -129,6 +23,27 @@ var ( BootstrapAddress string ) +// Initialize bootstrap configuration (no .env loading; defaults only) +func init() { + setDefaultBootstrapConfig() + updateBackwardCompatibilityConstants() +} + +// setDefaultBootstrapConfig sets default bootstrap configuration +func setDefaultBootstrapConfig() { + // Check if we're in production environment + BootstrapPeerIDs = []string{ + "12D3KooWNxt9bNvqftdqXg98JcUHreGxedWSZRUbyqXJ6CW7GaD4", + "12D3KooWGbdnA22bN24X2gyY1o9jozwTBq9wbfvwtJ7G4XQ9JgFm", + } + BootstrapAddresses = []string{ + "/ip4/57.129.81.31/tcp/4001/p2p/12D3KooWNxt9bNvqftdqXg98JcUHreGxedWSZRUbyqXJ6CW7GaD4", + "/ip4/38.242.250.186/tcp/4001/p2p/12D3KooWGbdnA22bN24X2gyY1o9jozwTBq9wbfvwtJ7G4XQ9JgFm", + } + + BootstrapPort = 4001 +} + // updateBackwardCompatibilityConstants updates the single constants for backward compatibility func updateBackwardCompatibilityConstants() { if len(BootstrapPeerIDs) > 0 { @@ -139,14 +54,6 @@ func updateBackwardCompatibilityConstants() { } } -// Call this after loading environment config -func init() { - // This runs after the first init() that calls loadEnvironmentConfig() - updateBackwardCompatibilityConstants() -} - -// Helper functions for working with bootstrap peers - // GetBootstrapPeers returns a copy of all bootstrap peer addresses func GetBootstrapPeers() []string { if len(BootstrapAddresses) == 0 { @@ -176,12 +83,6 @@ func AddBootstrapPeer(peerID, address string) { updateBackwardCompatibilityConstants() } -// ReloadEnvironmentConfig reloads the configuration from environment -func ReloadEnvironmentConfig() { - loadEnvironmentConfig() - updateBackwardCompatibilityConstants() -} - // GetEnvironmentInfo returns information about the current configuration func GetEnvironmentInfo() map[string]interface{} { return map[string]interface{}{ @@ -189,18 +90,5 @@ func GetEnvironmentInfo() map[string]interface{} { "bootstrap_peer_ids": GetBootstrapPeerIDs(), "bootstrap_port": BootstrapPort, "environment": os.Getenv("ENVIRONMENT"), - "config_loaded_from": getConfigSource(), } } - -// getConfigSource returns where the configuration was loaded from -func getConfigSource() string { - envPaths := []string{".env", "../.env", "../../.env"} - for _, path := range envPaths { - if _, err := os.Stat(path); err == nil { - abs, _ := filepath.Abs(path) - return abs - } - } - return "default values (no .env file found)" -} diff --git a/scripts/install-debros-network.sh b/scripts/install-debros-network.sh index 3f0c057..2e47f61 100755 --- a/scripts/install-debros-network.sh +++ b/scripts/install-debros-network.sh @@ -15,9 +15,9 @@ NOCOLOR='\033[0m' INSTALL_DIR="/opt/debros" REPO_URL="https://git.debros.io/DeBros/network.git" MIN_GO_VERSION="1.19" -NODE_PORT="4000" # LibP2P port for peer-to-peer communication -RQLITE_PORT="4001" # All nodes use same RQLite port to join same cluster -RAFT_PORT="4002" # All nodes use same Raft port +NODE_PORT="4001" # LibP2P port for peer-to-peer communication +RQLITE_PORT="5001" # All nodes use same RQLite HTTP port to join same cluster +RAFT_PORT="7001" # All nodes use same Raft port UPDATE_MODE=false NON_INTERACTIVE=false diff --git a/scripts/setup-production-security.sh b/scripts/setup-production-security.sh index 9d2b4fa..10e5c0b 100755 --- a/scripts/setup-production-security.sh +++ b/scripts/setup-production-security.sh @@ -69,14 +69,14 @@ sudo ufw default allow outgoing sudo ufw allow 22/tcp comment "SSH" # LibP2P P2P networking (public, encrypted) -sudo ufw allow 4000/tcp comment "LibP2P P2P" -sudo ufw allow 4000/udp comment "LibP2P QUIC" +sudo ufw allow 4001/tcp comment "LibP2P P2P" +sudo ufw allow 4001/udp comment "LibP2P QUIC" # RQLite ports (restrict to cluster IPs only) BOOTSTRAP_IPS=("57.129.81.31" "38.242.250.186") for ip in "${BOOTSTRAP_IPS[@]}"; do - sudo ufw allow from "$ip" to any port 4001 comment "RQLite HTTP from $ip" - sudo ufw allow from "$ip" to any port 4002 comment "RQLite Raft from $ip" + sudo ufw allow from "$ip" to any port 5001 comment "RQLite HTTP from $ip" + sudo ufw allow from "$ip" to any port 7001 comment "RQLite Raft from $ip" done # Enable firewall @@ -85,7 +85,7 @@ sudo ufw --force enable echo "🔧 Configuring RQLite cluster authentication..." # Update RQLite join addresses with authentication -AUTHENTICATED_JOIN_ADDRESS="http://$CLUSTER_USER:$CLUSTER_PASS@57.129.81.31:4001" +AUTHENTICATED_JOIN_ADDRESS="http://$CLUSTER_USER:$CLUSTER_PASS@57.129.81.31:5001" # Create environment file for authenticated connections cat > "$CONFIG_DIR/rqlite-env" << EOF @@ -106,9 +106,9 @@ cat > "$DEBROS_DIR/bin/rqlite-connect" << 'EOF' source /opt/debros/keys/rqlite-cluster-auth if [ "$1" = "cluster" ]; then - rqlite -H localhost -p 4001 -u "$RQLITE_CLUSTER_USER" -p "$RQLITE_CLUSTER_PASS" + rqlite -H localhost -p 5001 -u "$RQLITE_CLUSTER_USER" -p "$RQLITE_CLUSTER_PASS" elif [ "$1" = "api" ]; then - rqlite -H localhost -p 4001 -u "$RQLITE_API_USER" -p "$RQLITE_API_PASS" + rqlite -H localhost -p 5001 -u "$RQLITE_API_USER" -p "$RQLITE_API_PASS" else echo "Usage: $0 {cluster|api}" exit 1 @@ -124,8 +124,8 @@ echo "📋 Security Summary:" echo " - RQLite authentication enabled" echo " - Firewall configured with IP restrictions" echo " - Cluster credentials generated and stored" -echo " - Port 4000: Public LibP2P (encrypted P2P)" -echo " - Port 4001/4002: RQLite cluster (IP-restricted)" +echo " - Port 4001: Public LibP2P (encrypted P2P)" +echo " - Port 5001/7001: RQLite cluster (IP-restricted)" echo "" echo "🔐 Credentials stored in:" echo " - Users: $CONFIG_DIR/rqlite-users.json"