refactor: standardize ports (LibP2P 4001, RQLite 5001/7001) and remove .env configuration

This commit is contained in:
anonpenguin 2025-08-08 20:09:28 +03:00
parent 8d57fc8f98
commit b744f7f513
11 changed files with 192 additions and 491 deletions

View File

@ -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

View File

@ -350,14 +350,14 @@ database:
node: node:
data_dir: "./data/node" data_dir: "./data/node"
listen_addresses: listen_addresses:
- "/ip4/0.0.0.0/tcp/4002" - "/ip4/0.0.0.0/tcp/4001"
discovery: discovery:
bootstrap_peers: bootstrap_peers:
- "/ip4/127.0.0.1/tcp/4001/p2p/{BOOTSTRAP_PEER_ID}" - "/ip4/127.0.0.1/tcp/4001/p2p/{BOOTSTRAP_PEER_ID}"
discovery_interval: "10s" discovery_interval: "10s"
database: database:
rqlite_port: 5002 rqlite_port: 5001
rqlite_raft_port: 7002 rqlite_raft_port: 7001
rqlite_join_address: "http://localhost:5001" rqlite_join_address: "http://localhost:5001"
``` ```
@ -452,7 +452,7 @@ for _, peer := range peers {
} }
// Connect to specific peer // 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 ## Troubleshooting

View File

@ -23,40 +23,29 @@ test:
@echo "Running tests..." @echo "Running tests..."
go test -v ./... go test -v ./...
# Run node (auto-detects if bootstrap or regular based on configuration) # Run bootstrap node explicitly
run-node: run-node:
@echo "Starting network node..." @echo "Starting BOOTSTRAP node (role=bootstrap)..."
go run cmd/node/main.go -data ./data/node 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/<ID> HTTP=5002 RAFT=7002
run-node2: run-node2:
@echo "Starting second network node..." @echo "Starting REGULAR node2 (role=node)..."
go run cmd/node/main.go -id node2 @if [ -z "$(BOOTSTRAP)" ]; then echo "ERROR: Provide BOOTSTRAP multiaddr: make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/<ID> [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/<ID> HTTP=5003 RAFT=7003
run-node3: run-node3:
@echo "Starting third network node..." @echo "Starting REGULAR node3 (role=node)..."
go run cmd/node/main.go -id node3 @if [ -z "$(BOOTSTRAP)" ]; then echo "ERROR: Provide BOOTSTRAP multiaddr: make run-node3 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/<ID> [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: show-bootstrap:
@echo "Current bootstrap configuration from .env:" @echo "Provide bootstrap via flags, e.g.:"
@cat .env 2>/dev/null || echo "No .env file found - using defaults" @echo " make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/<PEER_ID> HTTP=5002 RAFT=7002"
# 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
# Run network CLI # Run network CLI
run-cli: run-cli:
@ -112,7 +101,6 @@ dev-setup: deps
@echo "Setting up development environment..." @echo "Setting up development environment..."
@mkdir -p data/bootstrap data/node data/node-node2 data/node-node3 @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 data/test-bootstrap data/test-node1 data/test-node2
@mkdir -p anchat/bin
@echo "Development setup complete!" @echo "Development setup complete!"
# Multi-node testing # Multi-node testing
@ -142,35 +130,31 @@ 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 first node (auto-detects as bootstrap in dev)" @echo "1. make run-node # Start bootstrap node"
@echo "2. make run-node2 # Start second node with different identity" @echo "2. make run-node2 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/<ID> HTTP=5002 RAFT=7002"
@echo "3. make run-node3 # Start third node with different identity" @echo "3. make run-node3 BOOTSTRAP=/ip4/127.0.0.1/tcp/4001/p2p/<ID> HTTP=5003 RAFT=7003"
@echo "4. make run-example # Test basic functionality" @echo "4. make run-example # Test basic functionality"
@echo "5. make run-anchat # Start messaging app" @echo "5. make cli-health # Check network health"
@echo "6. make show-bootstrap # Check bootstrap configuration" @echo "6. make cli-peers # List peers"
@echo "7. make cli-health # Check network health" @echo "7. make cli-storage-test # Test storage"
@echo "8. make cli-peers # List peers" @echo "8. make cli-pubsub-test # Test messaging"
@echo "9. make cli-storage-test # Test storage"
@echo "10. make cli-pubsub-test # Test messaging"
# Full development workflow # Full development workflow
dev: clean build build-anchat test dev: clean build test
@echo "Development workflow complete!" @echo "Development workflow complete!"
# Help # Help
help: help:
@echo "Available targets:" @echo "Available targets:"
@echo " build - Build all executables" @echo " build - Build all executables"
@echo " build-anchat - Build Anchat application"
@echo " clean - Clean build artifacts" @echo " clean - Clean build artifacts"
@echo " test - Run tests" @echo " test - Run tests"
@echo " run-node - Start network node (auto-detects bootstrap vs regular)" @echo " run-node - Start bootstrap node (role=bootstrap)"
@echo " run-node2 - Start second node with different identity" @echo " run-node2 - Start second node (role=node). Provide BOOTSTRAP, optional HTTP/RAFT"
@echo " run-node3 - Start third node with different identity" @echo " run-node3 - Start third node (role=node). Provide BOOTSTRAP, optional HTTP/RAFT"
@echo " run-example - Run usage example" @echo " run-example - Run usage example"
@echo " run-anchat - Run Anchat demo"
@echo " run-cli - Run network CLI help" @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-health - Check network health"
@echo " cli-peers - List network peers" @echo " cli-peers - List network peers"
@echo " cli-status - Get network status" @echo " cli-status - Get network status"

293
README.md
View File

@ -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) - [3. Build the Project](#3-build-the-project)
- [4. Start the Network](#4-start-the-network) - [4. Start the Network](#4-start-the-network)
- [5. Test with CLI](#5-test-with-cli) - [5. Test with CLI](#5-test-with-cli)
- [6. Test Anchat Messaging](#6-test-anchat-messaging)
- [Deployment](#deployment) - [Deployment](#deployment)
- [Production Installation Script](#production-installation-script) - [Production Installation Script](#production-installation-script)
- [One-Command Installation](#one-command-installation) - [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) - [Environment Setup](#environment-setup)
- [Configuration System](#configuration-system) - [Configuration System](#configuration-system)
- [Client Library Usage](#client-library-usage) - [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) - [Troubleshooting](#troubleshooting)
- [Common Issues](#common-issues) - [Common Issues](#common-issues)
- [Debug Commands](#debug-commands) - [Debug Commands](#debug-commands)
@ -165,11 +159,8 @@ Ensure these ports are available or configure firewall rules accordingly.
```bash ```bash
# Clone the repository # Clone the repository
git clone https://git.debros.io/DeBros/network-cluster.git git clone https://git.debros.io/DeBros/network.git
cd network-cluster cd network
# Copy environment configuration
cp .env.example .env
``` ```
### 2. Generate Bootstrap Identity (Development Only) ### 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 # Generate bootstrap peer identity
go run scripts/generate-bootstrap-identity.go go run scripts/generate-bootstrap-identity.go
# This will create data/bootstrap/identity.key and show the peer ID # This will create data/bootstrap/identity.key and show the peer ID (and multiaddr)
# Copy the peer ID and update your .env files # Save the printed peer ID to use with the -bootstrap flag
``` ```
**Important:** After generating the bootstrap identity, update both `.env` files: **Important:** After generating the bootstrap identity, copy the printed multiaddr
or peer ID for use with the `-bootstrap` flag when starting regular nodes.
```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
```
### 3. Build the Project ### 3. Build the Project
```bash ```bash
# Build all network executables # Build all network executables
make build make build
# Build Anchat application
cd anchat
make build
cd ..
# Or build everything at once
make build && make build-anchat
``` ```
### 4. Start the Network ### 4. Start the Network
@ -216,24 +190,33 @@ make build && make build-anchat
**Terminal 1 - Bootstrap Node:** **Terminal 1 - Bootstrap Node:**
```bash ```bash
make run-node # Start an explicit bootstrap node (LibP2P 4001, RQLite 5001/7001)
# This automatically detects and starts as bootstrap node on port 4001 go run cmd/node/main.go -role bootstrap -data ./data/bootstrap
# if the local machine matches bootstrap peer configuration
``` ```
**Terminal 2 - Regular Node:** **Terminal 2 - Regular Node:**
```bash ```bash
make run-node # Replace <BOOTSTRAP_PEER_ID> with the ID printed by the identity generator
# This automatically connects to bootstrap peers from .env go run cmd/node/main.go \
# No need to specify bootstrap manually anymore! -role node \
-id node2 \
-data ./data/node2 \
-bootstrap /ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_PEER_ID> \
-rqlite-http-port 5002 \
-rqlite-raft-port 7002
``` ```
**Terminal 3 - Another Node (optional):** **Terminal 3 - Another Node (optional):**
```bash ```bash
# For additional nodes, use different data directory go run cmd/node/main.go \
go run cmd/node/main.go -data ./data/node2 -role node \
-id node3 \
-data ./data/node3 \
-bootstrap /ip4/127.0.0.1/tcp/4001/p2p/<BOOTSTRAP_PEER_ID> \
-rqlite-http-port 5003 \
-rqlite-raft-port 7003
``` ```
### 5. Test with CLI ### 5. Test with CLI
@ -253,18 +236,6 @@ make show-bootstrap
./bin/cli peers ./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 ## Deployment
### Production Installation Script ### Production Installation Script
@ -430,7 +401,7 @@ sudo cp -r /opt/debros/keys /backup/
```bash ```bash
# Check if ports are open # 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 # Check service logs
sudo journalctl -u debros-node.service --since "1 hour ago" 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. 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 <multiaddr>`
- **RQLite ports**: `-rqlite-http-port` (default 5001), `-rqlite-raft-port` (default 7001)
#### Setup for Development Examples are shown in Quick Start above for local multi-node on a single machine.
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
```
## CLI Commands ## CLI Commands
The CLI and nodes now automatically load bootstrap peers from `.env` files - no manual configuration needed! The CLI can still accept `--bootstrap <multiaddr>` to override discovery when needed.
### Network Operations ### Network Operations
@ -568,7 +477,7 @@ The CLI and nodes now automatically load bootstrap peers from `.env` files - no
### Project Structure ### Project Structure
``` ```
network-cluster/ network/
├── cmd/ ├── cmd/
│ ├── bootstrap/ # Bootstrap node │ ├── bootstrap/ # Bootstrap node
│ ├── node/ # Regular network node │ ├── node/ # Regular network node
@ -580,21 +489,9 @@ network-cluster/
│ ├── storage/ # Storage service │ ├── storage/ # Storage service
│ ├── constants/ # Bootstrap configuration │ ├── constants/ # Bootstrap configuration
│ └── config/ # System configuration │ └── config/ # System configuration
├── anchat/ # Anchat messaging application ├── scripts/ # Helper scripts (install, security, tests)
│ ├── cmd/cli/ # Anchat CLI ├── scripts/ # Helper scripts (install, security, tests)
│ ├── 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
├── bin/ # Built executables ├── bin/ # Built executables
├── data/ # Runtime data directories
└── Makefile # Build and run commands
``` ```
### Building and Testing ### Building and Testing
@ -603,11 +500,6 @@ network-cluster/
# Build all network executables # Build all network executables
make build make build
# Build Anchat application
cd anchat && make build && cd ..
# or
make build-anchat
# Show current bootstrap configuration # Show current bootstrap configuration
make show-bootstrap make show-bootstrap
@ -631,19 +523,17 @@ make dev
```bash ```bash
# Copy environment templates # Copy environment templates
cp .env.example .env cp .env.example .env
cp anchat/.env.example anchat/.env
# Generate consistent bootstrap identity # Generate consistent bootstrap identity
go run scripts/generate-bootstrap-identity.go 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:** 2. **Build Everything:**
```bash ```bash
make build # Build network components make build # Build network components
make build-anchat # Build Anchat application
``` ```
3. **Start Development Cluster:** 3. **Start Development Cluster:**
@ -658,9 +548,6 @@ make dev
# Terminal 3: Test with CLI # Terminal 3: Test with CLI
./bin/cli health ./bin/cli health
./bin/cli peers ./bin/cli peers
# Terminal 4 & 5: Test Anchat
cd anchat && ./bin/anchat
``` ```
### Environment Setup ### Environment Setup
@ -689,7 +576,6 @@ make dev
```bash ```bash
# Setup .env files # Setup .env files
cp .env.example .env cp .env.example .env
cp anchat/.env.example anchat/.env
# Generate bootstrap identity # Generate bootstrap identity
go run scripts/generate-bootstrap-identity.go 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 <room> # Join a room
/leave # Leave current room
/create <room> [desc] # Create a new room
# Messaging
<message> # Send message to current room
/msg <user> <message> # Send private message
/me <action> # Send action message
# User management
/users # List users in current room
/nick <username> # 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 ## Troubleshooting
### Common Issues ### Common Issues
@ -857,7 +649,7 @@ The Anchat application also includes hardcoded fallback bootstrap peers in `anch
**Bootstrap peer not found / Peer ID mismatch:** **Bootstrap peer not found / Peer ID mismatch:**
- Generate a new bootstrap identity: `go run scripts/generate-bootstrap-identity.go` - 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` - Restart the bootstrap node: `make run-node`
- Check configuration: `make show-bootstrap` - 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` - Verify RQLite is properly installed: `rqlited --version`
- Check for port conflicts: `netstat -an | grep -E "(4001|5001|7001)"` - 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 ### Debug Commands
```bash ```bash
# Check current configuration # Check current configuration
make show-bootstrap make show-bootstrap
cat .env cat .env
cat anchat/.env
# Check running processes # Check running processes
ps aux | grep -E "(bootstrap|node|rqlite)" ps aux | grep -E "(bootstrap|node|rqlite)"
# Check port usage # 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 # Check bootstrap peer info
cat data/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 # Verify .env file syntax
grep -E "^[A-Z_]+=.*" .env grep -E "^[A-Z_]+=.*" .env
grep -E "^[A-Z_]+=.*" anchat/.env
``` ```
### Logs and Data ### Logs and Data
@ -937,7 +720,7 @@ grep -E "^[A-Z_]+=.*" anchat/.env
- RQLite data: `./data/<node>/rqlite/` - RQLite data: `./data/<node>/rqlite/`
- Peer info: `./data/<node>/peer.info` - Peer info: `./data/<node>/peer.info`
- Bootstrap identity: `./data/bootstrap/identity.key` - Bootstrap identity: `./data/bootstrap/identity.key`
- Environment config: `./.env`, `./anchat/.env` - Environment config: `./.env`
## License ## License

48
clear-ports.sh Executable file
View File

@ -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

View File

@ -10,10 +10,10 @@ import (
"strings" "strings"
"time" "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/client"
"git.debros.io/DeBros/network/pkg/constants" "git.debros.io/DeBros/network/pkg/constants"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
) )
var ( var (

View File

@ -23,6 +23,9 @@ func main() {
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)")
bootstrap = flag.String("bootstrap", "", "Bootstrap peer address (for manual override)") 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") help = flag.Bool("help", false, "Show help")
) )
flag.Parse() flag.Parse()
@ -32,8 +35,17 @@ func main() {
return return
} }
// 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 // Auto-detect if this is a bootstrap node based on configuration
isBootstrap := isBootstrapNode() isBootstrap = isBootstrapNode()
}
// Set default data directory if not provided // Set default data directory if not provided
if *dataDir == "" { if *dataDir == "" {
@ -48,8 +60,8 @@ func main() {
} }
} }
// LibP2P uses port 4000, RQLite uses 4001 // LibP2P uses port 4001, RQLite uses 5001 (HTTP) and 7001 (Raft)
port := 4000 port := 4001
// Create logger with appropriate component type // Create logger with appropriate component type
var logger *logging.StandardLogger var logger *logging.StandardLogger
@ -80,9 +92,9 @@ func main() {
fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", port), fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic", port),
} }
// All nodes use the same RQLite port (4001) to join the same cluster // RQLite ports (overridable for local multi-node on one host)
cfg.Database.RQLitePort = 4001 cfg.Database.RQLitePort = *rqlHTTP
cfg.Database.RQLiteRaftPort = 4002 cfg.Database.RQLiteRaftPort = *rqlRaft
if isBootstrap { if isBootstrap {
// Check if this is the primary bootstrap node (first in list) or secondary // Check if this is the primary bootstrap node (first in list) or secondary
@ -102,7 +114,7 @@ func main() {
if isSecondaryBootstrap { if isSecondaryBootstrap {
// Secondary bootstrap nodes join the primary bootstrap // Secondary bootstrap nodes join the primary bootstrap
primaryBootstrapHost := parseHostFromMultiaddr(bootstrapPeers[0]) 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) logger.Printf("Secondary bootstrap node - joining primary bootstrap at: %s", cfg.Database.RQLiteJoinAddress)
} else { } else {
// Primary bootstrap node doesn't join anyone - it starts the cluster // 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 // Extract IP from bootstrap peer for RQLite join
bootstrapHost := parseHostFromMultiaddr(*bootstrap) bootstrapHost := parseHostFromMultiaddr(*bootstrap)
if bootstrapHost != "" { 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) logger.Printf("Using extracted bootstrap host %s for RQLite join", bootstrapHost)
} else { } else {
logger.Printf("Warning: Could not extract host from bootstrap peer %s, using localhost fallback", *bootstrap) 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) logger.Printf("Using command line bootstrap peer: %s", *bootstrap)
} else { } else {
@ -133,18 +145,18 @@ func main() {
// Use the first bootstrap peer for RQLite join // Use the first bootstrap peer for RQLite join
bootstrapHost := parseHostFromMultiaddr(bootstrapPeers[0]) bootstrapHost := parseHostFromMultiaddr(bootstrapPeers[0])
if bootstrapHost != "" { 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) logger.Printf("Using extracted bootstrap host %s for RQLite join", bootstrapHost)
} else { } else {
logger.Printf("Warning: Could not extract host from bootstrap peer %s", bootstrapPeers[0]) logger.Printf("Warning: Could not extract host from bootstrap peer %s", bootstrapPeers[0])
// Try primary production server as fallback // Try primary production server as fallback
rqliteJoinAddr = "http://localhost:4001" rqliteJoinAddr = "http://localhost:5001"
} }
logger.Printf("Using environment bootstrap peers: %v", bootstrapPeers) logger.Printf("Using environment bootstrap peers: %v", bootstrapPeers)
} else { } else {
logger.Printf("Warning: No bootstrap peers configured") logger.Printf("Warning: No bootstrap peers configured")
// Default to localhost when no 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") logger.Printf("Using localhost fallback for RQLite join")
} }

View File

@ -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) 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 { func (d *DatabaseClientImpl) getRQLiteNodes() []string {
// Use bootstrap peer addresses from constants // Use bootstrap peer addresses from constants
// Import the constants package // Import the constants package
@ -207,7 +207,7 @@ func (d *DatabaseClientImpl) getRQLiteNodes() []string {
// Example multiaddr: /ip4/57.129.81.31/tcp/4001/p2p/12D3KooWQRK2duw5B5LXi8gA7HBBFiCsLvwyph2ZU9VBmvbE1Nei // Example multiaddr: /ip4/57.129.81.31/tcp/4001/p2p/12D3KooWQRK2duw5B5LXi8gA7HBBFiCsLvwyph2ZU9VBmvbE1Nei
parts := strings.Split(addr, "/") parts := strings.Split(addr, "/")
var host string 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++ { for i := 0; i < len(parts); i++ {
if parts[i] == "ip4" || parts[i] == "ip6" { if parts[i] == "ip4" || parts[i] == "ip6" {
host = parts[i+1] host = parts[i+1]
@ -215,15 +215,15 @@ func (d *DatabaseClientImpl) getRQLiteNodes() []string {
if parts[i] == "dns" || parts[i] == "dns4" || parts[i] == "dns6" { if parts[i] == "dns" || parts[i] == "dns4" || parts[i] == "dns6" {
host = parts[i+1] 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 != "" { if host != "" {
nodes = append(nodes, "http://"+host+":"+port) 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 { if len(nodes) == 0 {
nodes = append(nodes, "http://localhost:4001") nodes = append(nodes, "http://localhost:5001")
} }
return nodes return nodes
} }

View File

@ -2,11 +2,6 @@ package constants
import ( import (
"os" "os"
"path/filepath"
"strconv"
"strings"
"github.com/joho/godotenv"
) )
// Bootstrap node configuration // Bootstrap node configuration
@ -19,109 +14,8 @@ var (
BootstrapAddresses []string BootstrapAddresses []string
// BootstrapPort is the default port for bootstrap nodes (LibP2P) // 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) // Primary bootstrap peer ID (first in the list)
BootstrapPeerID string BootstrapPeerID string
@ -129,6 +23,27 @@ var (
BootstrapAddress string 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 // updateBackwardCompatibilityConstants updates the single constants for backward compatibility
func updateBackwardCompatibilityConstants() { func updateBackwardCompatibilityConstants() {
if len(BootstrapPeerIDs) > 0 { 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 // GetBootstrapPeers returns a copy of all bootstrap peer addresses
func GetBootstrapPeers() []string { func GetBootstrapPeers() []string {
if len(BootstrapAddresses) == 0 { if len(BootstrapAddresses) == 0 {
@ -176,12 +83,6 @@ func AddBootstrapPeer(peerID, address string) {
updateBackwardCompatibilityConstants() updateBackwardCompatibilityConstants()
} }
// ReloadEnvironmentConfig reloads the configuration from environment
func ReloadEnvironmentConfig() {
loadEnvironmentConfig()
updateBackwardCompatibilityConstants()
}
// GetEnvironmentInfo returns information about the current configuration // GetEnvironmentInfo returns information about the current configuration
func GetEnvironmentInfo() map[string]interface{} { func GetEnvironmentInfo() map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
@ -189,18 +90,5 @@ func GetEnvironmentInfo() map[string]interface{} {
"bootstrap_peer_ids": GetBootstrapPeerIDs(), "bootstrap_peer_ids": GetBootstrapPeerIDs(),
"bootstrap_port": BootstrapPort, "bootstrap_port": BootstrapPort,
"environment": os.Getenv("ENVIRONMENT"), "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)"
}

View File

@ -15,9 +15,9 @@ NOCOLOR='\033[0m'
INSTALL_DIR="/opt/debros" INSTALL_DIR="/opt/debros"
REPO_URL="https://git.debros.io/DeBros/network.git" REPO_URL="https://git.debros.io/DeBros/network.git"
MIN_GO_VERSION="1.19" MIN_GO_VERSION="1.19"
NODE_PORT="4000" # LibP2P port for peer-to-peer communication NODE_PORT="4001" # LibP2P port for peer-to-peer communication
RQLITE_PORT="4001" # All nodes use same RQLite port to join same cluster RQLITE_PORT="5001" # All nodes use same RQLite HTTP port to join same cluster
RAFT_PORT="4002" # All nodes use same Raft port RAFT_PORT="7001" # All nodes use same Raft port
UPDATE_MODE=false UPDATE_MODE=false
NON_INTERACTIVE=false NON_INTERACTIVE=false

View File

@ -69,14 +69,14 @@ sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment "SSH" sudo ufw allow 22/tcp comment "SSH"
# LibP2P P2P networking (public, encrypted) # LibP2P P2P networking (public, encrypted)
sudo ufw allow 4000/tcp comment "LibP2P P2P" sudo ufw allow 4001/tcp comment "LibP2P P2P"
sudo ufw allow 4000/udp comment "LibP2P QUIC" sudo ufw allow 4001/udp comment "LibP2P QUIC"
# RQLite ports (restrict to cluster IPs only) # RQLite ports (restrict to cluster IPs only)
BOOTSTRAP_IPS=("57.129.81.31" "38.242.250.186") BOOTSTRAP_IPS=("57.129.81.31" "38.242.250.186")
for ip in "${BOOTSTRAP_IPS[@]}"; do 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 5001 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 7001 comment "RQLite Raft from $ip"
done done
# Enable firewall # Enable firewall
@ -85,7 +85,7 @@ sudo ufw --force enable
echo "🔧 Configuring RQLite cluster authentication..." echo "🔧 Configuring RQLite cluster authentication..."
# Update RQLite join addresses with 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 # Create environment file for authenticated connections
cat > "$CONFIG_DIR/rqlite-env" << EOF cat > "$CONFIG_DIR/rqlite-env" << EOF
@ -106,9 +106,9 @@ cat > "$DEBROS_DIR/bin/rqlite-connect" << 'EOF'
source /opt/debros/keys/rqlite-cluster-auth source /opt/debros/keys/rqlite-cluster-auth
if [ "$1" = "cluster" ]; then 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 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 else
echo "Usage: $0 {cluster|api}" echo "Usage: $0 {cluster|api}"
exit 1 exit 1
@ -124,8 +124,8 @@ echo "📋 Security Summary:"
echo " - RQLite authentication enabled" echo " - RQLite authentication enabled"
echo " - Firewall configured with IP restrictions" echo " - Firewall configured with IP restrictions"
echo " - Cluster credentials generated and stored" echo " - Cluster credentials generated and stored"
echo " - Port 4000: Public LibP2P (encrypted P2P)" echo " - Port 4001: Public LibP2P (encrypted P2P)"
echo " - Port 4001/4002: RQLite cluster (IP-restricted)" echo " - Port 5001/7001: RQLite cluster (IP-restricted)"
echo "" echo ""
echo "🔐 Credentials stored in:" echo "🔐 Credentials stored in:"
echo " - Users: $CONFIG_DIR/rqlite-users.json" echo " - Users: $CONFIG_DIR/rqlite-users.json"