Compare commits

..

No commits in common. "main" and "v0.12.1-beta" have entirely different histories.

8 changed files with 614 additions and 452 deletions

View File

@ -1,69 +1,7 @@
# Network - Distributed P2P Database System v0.12.5-beta # Network - Distributed P2P Database System
A distributed peer-to-peer network built with Go and LibP2P, providing decentralized database capabilities with RQLite consensus and replication. A distributed peer-to-peer network built with Go and LibP2P, providing decentralized database capabilities with RQLite consensus and replication.
## Table of Contents
- [Features](#features)
- [System Requirements](#system-requirements)
- [Software Dependencies](#software-dependencies)
- [Installation](#installation)
- [macOS](#macos)
- [Ubuntu/Debian](#ubuntudebian)
- [Windows](#windows)
- [Hardware Requirements](#hardware-requirements)
- [Network Ports](#network-ports)
- [Quick Start](#quick-start)
- [1. Clone and Setup Environment](#1-clone-and-setup-environment)
- [2. Generate Bootstrap Identity (Development Only)](#2-generate-bootstrap-identity-development-only)
- [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)
- [What the Script Does](#what-the-script-does)
- [Directory Structure](#directory-structure)
- [Node Types](#node-types)
- [Service Management](#service-management)
- [Configuration Files](#configuration-files)
- [Security Features](#security-features)
- [Network Discovery](#network-discovery)
- [Updates and Maintenance](#updates-and-maintenance)
- [Monitoring and Troubleshooting](#monitoring-and-troubleshooting)
- [Environment Configuration](#environment-configuration)
- [Bootstrap Peers Configuration](#bootstrap-peers-configuration)
- [Setup for Development](#setup-for-development)
- [Configuration Files](#configuration-files-1)
- [Multiple Bootstrap Peers](#multiple-bootstrap-peers)
- [Checking Configuration](#checking-configuration)
- [CLI Commands](#cli-commands)
- [Network Operations](#network-operations)
- [Storage Operations](#storage-operations)
- [Database Operations](#database-operations)
- [Pub/Sub Messaging](#pubsub-messaging)
- [CLI Options](#cli-options)
- [Development](#development)
- [Project Structure](#project-structure)
- [Building and Testing](#building-and-testing)
- [Development Workflow](#development-workflow)
- [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)
- [Environment-specific Issues](#environment-specific-issues)
- [Configuration Validation](#configuration-validation)
- [Logs and Data](#logs-and-data)
- [License](#license)
## Features ## Features
- **Peer-to-Peer Networking**: Built on LibP2P for robust P2P communication - **Peer-to-Peer Networking**: Built on LibP2P for robust P2P communication
@ -274,7 +212,7 @@ For production deployments on Linux servers, we provide an automated installatio
```bash ```bash
# Download and run the installation script # Download and run the installation script
curl -sSL https://git.debros.io/DeBros/network/raw/branch/main/scripts/install-debros-network.sh | bash curl -sSL https://raw.githubusercontent.com/DeBrosOfficial/debros-network/main/scripts/install-debros-network.sh | bash
``` ```
#### What the Script Does #### What the Script Does
@ -441,7 +379,7 @@ The installation script implements production security best practices:
```bash ```bash
# Update to latest version (re-run the installation script) # Update to latest version (re-run the installation script)
curl -sSL https://git.debros.io/DeBros/network/raw/branch/main/scripts/install-debros-network.sh | bash curl -sSL https://raw.githubusercontent.com/DeBrosOfficial/debros-network/main/scripts/install-debros-network.sh | bash
# Manual source update # Manual source update
cd /opt/debros/src cd /opt/debros/src

View File

@ -10,7 +10,7 @@ import (
"strings" "strings"
"time" "time"
"git.debros.io/DeBros/network/pkg/client" "network/pkg/client"
) )
var ( var (

View File

@ -9,9 +9,9 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"git.debros.io/DeBros/network/pkg/config" "network/pkg/config"
"git.debros.io/DeBros/network/pkg/constants" "network/pkg/constants"
"git.debros.io/DeBros/network/pkg/node" "network/pkg/node"
) )
func main() { func main() {

View File

@ -5,7 +5,7 @@ import (
"log" "log"
"time" "time"
"git.debros.io/DeBros/network/pkg/client" "network/pkg/client"
) )
func main() { func main() {

554
install-debros-network.sh Executable file
View File

@ -0,0 +1,554 @@
#!/bin/bash
set -e # Exit on any error
trap 'echo -e "${RED}An error occurred. Installation aborted.${NOCOLOR}"; exit 1' ERR
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
BLUE='\033[38;2;2;128;175m'
YELLOW='\033[1;33m'
NOCOLOR='\033[0m'
# Default values
INSTALL_DIR="/opt/debros"
REPO_URL="https://github.com/DeBrosOfficial/debros-network.git"
MIN_GO_VERSION="1.19"
BOOTSTRAP_PORT="4001"
NODE_PORT="4002"
RQLITE_BOOTSTRAP_PORT="5001"
RQLITE_NODE_PORT="5002"
RAFT_BOOTSTRAP_PORT="7001"
RAFT_NODE_PORT="7002"
log() {
echo -e "${CYAN}[$(date '+%Y-%m-%d %H:%M:%S')]${NOCOLOR} $1"
}
error() {
echo -e "${RED}[ERROR]${NOCOLOR} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NOCOLOR} $1"
}
warning() {
echo -e "${YELLOW}[WARNING]${NOCOLOR} $1"
}
# Check if running as root
if [[ $EUID -eq 0 ]]; then
error "This script should not be run as root. Please run as a regular user with sudo privileges."
exit 1
fi
# Check if sudo is available
if ! command -v sudo &>/dev/null; then
error "sudo command not found. Please ensure you have sudo privileges."
exit 1
fi
# Detect OS
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
VERSION=$VERSION_ID
else
error "Cannot detect operating system"
exit 1
fi
case $OS in
ubuntu|debian)
PACKAGE_MANAGER="apt"
;;
centos|rhel|fedora)
PACKAGE_MANAGER="yum"
if command -v dnf &> /dev/null; then
PACKAGE_MANAGER="dnf"
fi
;;
*)
error "Unsupported operating system: $OS"
exit 1
;;
esac
log "Detected OS: $OS $VERSION"
}
# Check Go installation and version
check_go_installation() {
if command -v go &> /dev/null; then
GO_VERSION=$(go version | awk '{print $3}' | sed 's/go//')
log "Found Go version: $GO_VERSION"
# Compare versions (simplified)
if [ "$(printf '%s\n' "$MIN_GO_VERSION" "$GO_VERSION" | sort -V | head -n1)" = "$MIN_GO_VERSION" ]; then
success "Go version is sufficient"
return 0
else
warning "Go version $GO_VERSION is too old. Minimum required: $MIN_GO_VERSION"
return 1
fi
else
log "Go not found on system"
return 1
fi
}
# Install Go
install_go() {
log "Installing Go..."
case $PACKAGE_MANAGER in
apt)
sudo apt update
sudo apt install -y wget
;;
yum|dnf)
sudo $PACKAGE_MANAGER install -y wget
;;
esac
# Download and install Go
GO_TARBALL="go1.21.0.linux-amd64.tar.gz"
ARCH=$(uname -m)
if [ "$ARCH" = "aarch64" ]; then
GO_TARBALL="go1.21.0.linux-arm64.tar.gz"
fi
cd /tmp
wget -q "https://golang.org/dl/$GO_TARBALL"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "$GO_TARBALL"
# Add Go to PATH
if ! grep -q "/usr/local/go/bin" ~/.bashrc; then
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
fi
export PATH=$PATH:/usr/local/go/bin
success "Go installed successfully"
}
# Install system dependencies
install_dependencies() {
log "Installing system dependencies..."
case $PACKAGE_MANAGER in
apt)
sudo apt update
sudo apt install -y git make build-essential curl
;;
yum|dnf)
sudo $PACKAGE_MANAGER groupinstall -y "Development Tools"
sudo $PACKAGE_MANAGER install -y git make curl
;;
esac
success "System dependencies installed"
}
# Check port availability
check_ports() {
local ports=($BOOTSTRAP_PORT $NODE_PORT $RQLITE_BOOTSTRAP_PORT $RQLITE_NODE_PORT $RAFT_BOOTSTRAP_PORT $RAFT_NODE_PORT)
for port in "${ports[@]}"; do
if sudo netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then
error "Port $port is already in use. Please free it up and try again."
exit 1
fi
done
success "All required ports are available"
}
# Configuration wizard
configuration_wizard() {
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN} DeBros Network Configuration Wizard ${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}"
# Node type selection
while true; do
echo -e "${GREEN}Select node type:${NOCOLOR}"
echo -e "${CYAN}1) Bootstrap Node (Network entry point)${NOCOLOR}"
echo -e "${CYAN}2) Regular Node (Connects to existing network)${NOCOLOR}"
read -rp "Enter your choice (1 or 2): " NODE_TYPE_CHOICE
case $NODE_TYPE_CHOICE in
1)
NODE_TYPE="bootstrap"
break
;;
2)
NODE_TYPE="regular"
break
;;
*)
error "Invalid choice. Please enter 1 or 2."
;;
esac
done
# Solana wallet address
log "${GREEN}Enter your Solana wallet address to be eligible 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
# Data directory
read -rp "Installation directory [default: $INSTALL_DIR]: " CUSTOM_INSTALL_DIR
if [[ -n "$CUSTOM_INSTALL_DIR" ]]; then
INSTALL_DIR="$CUSTOM_INSTALL_DIR"
fi
# Firewall configuration
read -rp "Configure firewall automatically? (yes/no) [default: yes]: " CONFIGURE_FIREWALL
CONFIGURE_FIREWALL="${CONFIGURE_FIREWALL:-yes}"
success "Configuration completed"
}
# Create user and directories
setup_directories() {
log "Setting up directories and permissions..."
# Create debros user if it doesn't exist
if ! id "debros" &>/dev/null; then
sudo useradd -r -s /bin/false -d "$INSTALL_DIR" debros
log "Created debros user"
fi
# Create directory structure
sudo mkdir -p "$INSTALL_DIR"/{bin,configs,keys,data,logs}
sudo mkdir -p "$INSTALL_DIR/keys/$NODE_TYPE"
sudo mkdir -p "$INSTALL_DIR/data/$NODE_TYPE"/{rqlite,storage}
# Set ownership and permissions
sudo chown -R debros:debros "$INSTALL_DIR"
sudo chmod 755 "$INSTALL_DIR"
sudo chmod 700 "$INSTALL_DIR/keys"
sudo chmod 600 "$INSTALL_DIR/keys/$NODE_TYPE" 2>/dev/null || true
success "Directory structure created"
}
# Clone or update repository
setup_source_code() {
log "Setting up source code..."
if [ -d "$INSTALL_DIR/src" ]; then
log "Updating existing repository..."
cd "$INSTALL_DIR/src"
sudo -u debros git pull
else
log "Cloning repository..."
sudo -u debros git clone "$REPO_URL" "$INSTALL_DIR/src"
cd "$INSTALL_DIR/src"
fi
success "Source code ready"
}
# Generate identity key
generate_identity() {
log "Generating node identity..."
cd "$INSTALL_DIR/src"
# Create a temporary Go program for key generation
cat > /tmp/generate_identity.go << 'EOF'
package main
import (
"crypto/rand"
"fmt"
"os"
"path/filepath"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: go run generate_identity.go <key_file_path>")
os.Exit(1)
}
keyFile := os.Args[1]
// Generate identity
priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, rand.Reader)
if err != nil {
panic(err)
}
// Get peer ID
peerID, err := peer.IDFromPublicKey(pub)
if err != nil {
panic(err)
}
// Marshal private key
data, err := crypto.MarshalPrivateKey(priv)
if err != nil {
panic(err)
}
// Create directory
if err := os.MkdirAll(filepath.Dir(keyFile), 0700); err != nil {
panic(err)
}
// Save identity
if err := os.WriteFile(keyFile, data, 0600); err != nil {
panic(err)
}
fmt.Printf("Generated Peer ID: %s\n", peerID.String())
fmt.Printf("Identity saved to: %s\n", keyFile)
}
EOF
# Generate the identity key
sudo -u debros go run /tmp/generate_identity.go "$INSTALL_DIR/keys/$NODE_TYPE/identity.key"
rm /tmp/generate_identity.go
success "Node identity generated"
}
# Build binaries
build_binaries() {
log "Building DeBros Network binaries..."
cd "$INSTALL_DIR/src"
# Build all binaries
sudo -u debros make build
# Copy binaries to installation directory
sudo cp bin/* "$INSTALL_DIR/bin/"
sudo chown debros:debros "$INSTALL_DIR/bin/"*
success "Binaries built and installed"
}
# Generate configuration files
generate_configs() {
log "Generating configuration files..."
if [ "$NODE_TYPE" = "bootstrap" ]; then
cat > /tmp/config.yaml << EOF
node:
data_dir: "$INSTALL_DIR/data/bootstrap"
key_file: "$INSTALL_DIR/keys/bootstrap/identity.key"
listen_addresses:
- "/ip4/0.0.0.0/tcp/$BOOTSTRAP_PORT"
solana_wallet: "$SOLANA_WALLET"
database:
rqlite_port: $RQLITE_BOOTSTRAP_PORT
rqlite_raft_port: $RAFT_BOOTSTRAP_PORT
logging:
level: "info"
file: "$INSTALL_DIR/logs/bootstrap.log"
EOF
else
cat > /tmp/config.yaml << EOF
node:
data_dir: "$INSTALL_DIR/data/node"
key_file: "$INSTALL_DIR/keys/node/identity.key"
listen_addresses:
- "/ip4/0.0.0.0/tcp/$NODE_PORT"
solana_wallet: "$SOLANA_WALLET"
database:
rqlite_port: $RQLITE_NODE_PORT
rqlite_raft_port: $RAFT_NODE_PORT
logging:
level: "info"
file: "$INSTALL_DIR/logs/node.log"
EOF
fi
sudo mv /tmp/config.yaml "$INSTALL_DIR/configs/$NODE_TYPE.yaml"
sudo chown debros:debros "$INSTALL_DIR/configs/$NODE_TYPE.yaml"
success "Configuration files generated"
}
# Configure firewall
configure_firewall() {
if [[ "$CONFIGURE_FIREWALL" == "yes" ]]; then
log "Configuring firewall..."
if command -v ufw &> /dev/null; then
if [ "$NODE_TYPE" = "bootstrap" ]; then
sudo ufw allow $BOOTSTRAP_PORT
sudo ufw allow $RQLITE_BOOTSTRAP_PORT
sudo ufw allow $RAFT_BOOTSTRAP_PORT
else
sudo ufw allow $NODE_PORT
sudo ufw allow $RQLITE_NODE_PORT
sudo ufw allow $RAFT_NODE_PORT
fi
# Enable ufw if not already active
UFW_STATUS=$(sudo ufw status | grep -o "Status: [a-z]*" | awk '{print $2}' || echo "inactive")
if [[ "$UFW_STATUS" != "active" ]]; then
echo "y" | sudo ufw enable
fi
success "Firewall configured"
else
warning "UFW not found. Please configure firewall manually."
fi
fi
}
# Create systemd service
create_systemd_service() {
log "Creating systemd service..."
cat > /tmp/debros-$NODE_TYPE.service << EOF
[Unit]
Description=DeBros Network $NODE_TYPE Node
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=debros
Group=debros
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/bin/$NODE_TYPE -config $INSTALL_DIR/configs/$NODE_TYPE.yaml
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=debros-$NODE_TYPE
# Security settings
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=$INSTALL_DIR
[Install]
WantedBy=multi-user.target
EOF
sudo mv /tmp/debros-$NODE_TYPE.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable debros-$NODE_TYPE.service
success "Systemd service created and enabled"
}
# Start the service
start_service() {
log "Starting DeBros Network $NODE_TYPE node..."
sudo systemctl start debros-$NODE_TYPE.service
sleep 3
if systemctl is-active --quiet debros-$NODE_TYPE.service; then
success "DeBros Network $NODE_TYPE node started successfully"
else
error "Failed to start DeBros Network $NODE_TYPE node"
log "Check logs with: sudo journalctl -u debros-$NODE_TYPE.service"
exit 1
fi
}
# Display banner
display_banner() {
echo -e "${BLUE}========================================================================${NOCOLOR}"
echo -e "${CYAN}
____ ____ _ _ _ _
| _ \ ___| __ ) _ __ ___ ___ | \ | | ___| |___ _____ _ __| | __
| | | |/ _ \ _ \| __/ _ \/ __| | \| |/ _ \ __\ \ /\ / / _ \| __| |/ /
| |_| | __/ |_) | | | (_) \__ \ | |\ | __/ |_ \ V V / (_) | | | <
|____/ \___|____/|_| \___/|___/ |_| \_|\___|\__| \_/\_/ \___/|_| |_|\_\\
${NOCOLOR}"
echo -e "${BLUE}========================================================================${NOCOLOR}"
}
# Main installation function
main() {
display_banner
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN} Starting DeBros Network Installation ${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}"
detect_os
check_ports
# Check and install Go if needed
if ! check_go_installation; then
install_go
fi
install_dependencies
configuration_wizard
setup_directories
setup_source_code
generate_identity
build_binaries
generate_configs
configure_firewall
create_systemd_service
start_service
# Display completion information
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN} Installation Complete! ${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Node Type:${NOCOLOR} ${CYAN}$NODE_TYPE${NOCOLOR}"
log "${GREEN}Installation Directory:${NOCOLOR} ${CYAN}$INSTALL_DIR${NOCOLOR}"
log "${GREEN}Configuration:${NOCOLOR} ${CYAN}$INSTALL_DIR/configs/$NODE_TYPE.yaml${NOCOLOR}"
log "${GREEN}Logs:${NOCOLOR} ${CYAN}$INSTALL_DIR/logs/$NODE_TYPE.log${NOCOLOR}"
if [ "$NODE_TYPE" = "bootstrap" ]; then
log "${GREEN}Bootstrap Port:${NOCOLOR} ${CYAN}$BOOTSTRAP_PORT${NOCOLOR}"
log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_BOOTSTRAP_PORT${NOCOLOR}"
log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_BOOTSTRAP_PORT${NOCOLOR}"
else
log "${GREEN}Node Port:${NOCOLOR} ${CYAN}$NODE_PORT${NOCOLOR}"
log "${GREEN}RQLite Port:${NOCOLOR} ${CYAN}$RQLITE_NODE_PORT${NOCOLOR}"
log "${GREEN}Raft Port:${NOCOLOR} ${CYAN}$RAFT_NODE_PORT${NOCOLOR}"
fi
log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Management Commands:${NOCOLOR}"
log "${CYAN} - sudo systemctl status debros-$NODE_TYPE${NOCOLOR} (Check status)"
log "${CYAN} - sudo systemctl restart debros-$NODE_TYPE${NOCOLOR} (Restart service)"
log "${CYAN} - sudo systemctl stop debros-$NODE_TYPE${NOCOLOR} (Stop service)"
log "${CYAN} - sudo systemctl start debros-$NODE_TYPE${NOCOLOR} (Start service)"
log "${CYAN} - sudo journalctl -u debros-$NODE_TYPE.service -f${NOCOLOR} (View logs)"
log "${CYAN} - $INSTALL_DIR/bin/cli${NOCOLOR} (Use CLI tools)"
log "${BLUE}==================================================${NOCOLOR}"
success "DeBros Network $NODE_TYPE node is now running!"
log "${CYAN}For documentation visit: https://docs.debros.io${NOCOLOR}"
}
# Run main function
main "$@"

View File

@ -19,9 +19,9 @@ import (
libp2ppubsub "github.com/libp2p/go-libp2p-pubsub" libp2ppubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns" "github.com/libp2p/go-libp2p/p2p/discovery/mdns"
"git.debros.io/DeBros/network/pkg/discovery" "network/pkg/discovery"
"git.debros.io/DeBros/network/pkg/pubsub" "network/pkg/pubsub"
"git.debros.io/DeBros/network/pkg/storage" "network/pkg/storage"
) )
// Client implements the NetworkClient interface // Client implements the NetworkClient interface

View File

@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
"git.debros.io/DeBros/network/pkg/storage" "network/pkg/storage"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"

View File

@ -13,7 +13,7 @@ NOCOLOR='\033[0m'
# Default values # Default values
INSTALL_DIR="/opt/debros" INSTALL_DIR="/opt/debros"
REPO_URL="https://git.debros.io/DeBros/network.git" REPO_URL="https://github.com/DeBrosOfficial/debros-network.git"
MIN_GO_VERSION="1.19" MIN_GO_VERSION="1.19"
BOOTSTRAP_PORT="4001" BOOTSTRAP_PORT="4001"
NODE_PORT="4002" NODE_PORT="4002"
@ -21,19 +21,11 @@ RQLITE_BOOTSTRAP_PORT="5001"
RQLITE_NODE_PORT="5002" RQLITE_NODE_PORT="5002"
RAFT_BOOTSTRAP_PORT="7001" RAFT_BOOTSTRAP_PORT="7001"
RAFT_NODE_PORT="7002" RAFT_NODE_PORT="7002"
UPDATE_MODE=false
NON_INTERACTIVE=false
log() { log() {
echo -e "${CYAN}[$(date '+%Y-%m-%d %H:%M:%S')]${NOCOLOR} $1" echo -e "${CYAN}[$(date '+%Y-%m-%d %H:%M:%S')]${NOCOLOR} $1"
} }
# Check if running non-interactively (piped from curl)
if [ ! -t 0 ]; then
NON_INTERACTIVE=true
log "Running in non-interactive mode"
fi
error() { error() {
echo -e "${RED}[ERROR]${NOCOLOR} $1" echo -e "${RED}[ERROR]${NOCOLOR} $1"
} }
@ -88,97 +80,6 @@ detect_os() {
log "Detected OS: $OS $VERSION" log "Detected OS: $OS $VERSION"
} }
# Check if DeBros Network is already installed
check_existing_installation() {
if [ -d "$INSTALL_DIR" ] && [ -f "$INSTALL_DIR/bin/bootstrap" ] && [ -f "$INSTALL_DIR/bin/node" ]; then
log "Found existing DeBros Network installation at $INSTALL_DIR"
# Check if services are running
BOOTSTRAP_RUNNING=false
NODE_RUNNING=false
if systemctl is-active --quiet debros-bootstrap.service 2>/dev/null; then
BOOTSTRAP_RUNNING=true
log "Bootstrap service is currently running"
fi
if systemctl is-active --quiet debros-node.service 2>/dev/null; then
NODE_RUNNING=true
log "Node service is currently running"
fi
if [ "$NON_INTERACTIVE" = true ]; then
log "Non-interactive mode: updating existing installation"
UPDATE_MODE=true
return 0
fi
echo -e "${YELLOW}Existing installation detected!${NOCOLOR}"
echo -e "${CYAN}Options:${NOCOLOR}"
echo -e "${CYAN}1) Update existing installation${NOCOLOR}"
echo -e "${CYAN}2) Remove and reinstall${NOCOLOR}"
echo -e "${CYAN}3) Exit installer${NOCOLOR}"
while true; do
read -rp "Enter your choice (1, 2, or 3): " EXISTING_CHOICE
case $EXISTING_CHOICE in
1)
UPDATE_MODE=true
log "Will update existing installation"
return 0
;;
2)
log "Will remove and reinstall"
remove_existing_installation
UPDATE_MODE=false
return 0
;;
3)
log "Installation cancelled by user"
exit 0
;;
*)
error "Invalid choice. Please enter 1, 2, or 3."
;;
esac
done
else
UPDATE_MODE=false
return 0
fi
}
# Remove existing installation
remove_existing_installation() {
log "Removing existing installation..."
# Stop services if they exist
for service in debros-bootstrap debros-node; do
if systemctl list-unit-files | grep -q "$service.service"; then
log "Stopping $service service..."
sudo systemctl stop $service.service 2>/dev/null || true
sudo systemctl disable $service.service 2>/dev/null || true
sudo rm -f /etc/systemd/system/$service.service
fi
done
sudo systemctl daemon-reload
# Remove installation directory
if [ -d "$INSTALL_DIR" ]; then
sudo rm -rf "$INSTALL_DIR"
log "Removed installation directory"
fi
# Remove debros user
if id "debros" &>/dev/null; then
sudo userdel debros 2>/dev/null || true
log "Removed debros user"
fi
success "Existing installation removed"
}
# Check Go installation and version # Check Go installation and version
check_go_installation() { check_go_installation() {
if command -v go &> /dev/null; then if command -v go &> /dev/null; then
@ -226,140 +127,31 @@ install_go() {
sudo rm -rf /usr/local/go sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "$GO_TARBALL" sudo tar -C /usr/local -xzf "$GO_TARBALL"
# Add Go to system-wide PATH # Add Go to PATH
if ! grep -q "/usr/local/go/bin" /etc/environment 2>/dev/null; then
echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin"' | sudo tee /etc/environment > /dev/null
fi
# Also add to current user's bashrc for compatibility
if ! grep -q "/usr/local/go/bin" ~/.bashrc; then if ! grep -q "/usr/local/go/bin" ~/.bashrc; then
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
fi fi
# Update current session PATH
export PATH=$PATH:/usr/local/go/bin export PATH=$PATH:/usr/local/go/bin
success "Go installed successfully" success "Go installed successfully"
} }
# Install system dependencies # Install system dependencies
install_dependencies() { install_dependencies() {
log "Checking system dependencies..." log "Installing system dependencies..."
# Check which dependencies are missing
MISSING_DEPS=()
case $PACKAGE_MANAGER in case $PACKAGE_MANAGER in
apt) apt)
# Check for required packages sudo apt update
for pkg in git make build-essential curl; do sudo apt install -y git make build-essential curl
if ! dpkg -l | grep -q "^ii $pkg "; then
MISSING_DEPS+=($pkg)
fi
done
if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
log "Installing missing dependencies: ${MISSING_DEPS[*]}"
sudo apt update
sudo apt install -y "${MISSING_DEPS[@]}"
else
success "All system dependencies already installed"
fi
;; ;;
yum|dnf) yum|dnf)
# Check for required packages sudo $PACKAGE_MANAGER groupinstall -y "Development Tools"
for pkg in git make curl; do sudo $PACKAGE_MANAGER install -y git make curl
if ! rpm -q $pkg &>/dev/null; then
MISSING_DEPS+=($pkg)
fi
done
# Check for development tools
if ! rpm -q gcc &>/dev/null; then
MISSING_DEPS+=("Development Tools")
fi
if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
log "Installing missing dependencies: ${MISSING_DEPS[*]}"
if [[ " ${MISSING_DEPS[*]} " =~ " Development Tools " ]]; then
sudo $PACKAGE_MANAGER groupinstall -y "Development Tools"
fi
# Remove "Development Tools" from array for individual package installation
MISSING_DEPS=($(printf '%s\n' "${MISSING_DEPS[@]}" | grep -v "Development Tools"))
if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
sudo $PACKAGE_MANAGER install -y "${MISSING_DEPS[@]}"
fi
else
success "All system dependencies already installed"
fi
;; ;;
esac esac
success "System dependencies ready" success "System dependencies installed"
}
# Install RQLite
install_rqlite() {
# Check if RQLite is already installed
if command -v rqlited &> /dev/null; then
RQLITE_VERSION=$(rqlited -version | head -n1 | awk '{print $2}')
log "Found RQLite version: $RQLITE_VERSION"
success "RQLite already installed"
return 0
fi
log "Installing RQLite..."
# Determine architecture
ARCH=$(uname -m)
case $ARCH in
x86_64)
RQLITE_ARCH="amd64"
;;
aarch64|arm64)
RQLITE_ARCH="arm64"
;;
armv7l)
RQLITE_ARCH="arm"
;;
*)
error "Unsupported architecture: $ARCH"
exit 1
;;
esac
# Download and install RQLite
RQLITE_VERSION="8.30.0"
RQLITE_TARBALL="rqlite-v${RQLITE_VERSION}-linux-${RQLITE_ARCH}.tar.gz"
RQLITE_URL="https://github.com/rqlite/rqlite/releases/download/v${RQLITE_VERSION}/${RQLITE_TARBALL}"
cd /tmp
if ! wget -q "$RQLITE_URL"; then
error "Failed to download RQLite from $RQLITE_URL"
exit 1
fi
# Extract and install RQLite binaries
tar -xzf "$RQLITE_TARBALL"
RQLITE_DIR="rqlite-v${RQLITE_VERSION}-linux-${RQLITE_ARCH}"
# Install RQLite binaries to system PATH
sudo cp "$RQLITE_DIR/rqlited" /usr/local/bin/
sudo cp "$RQLITE_DIR/rqlite" /usr/local/bin/
sudo chmod +x /usr/local/bin/rqlited
sudo chmod +x /usr/local/bin/rqlite
# Cleanup
rm -rf "$RQLITE_TARBALL" "$RQLITE_DIR"
# Verify installation
if command -v rqlited &> /dev/null; then
INSTALLED_VERSION=$(rqlited -version | head -n1 | awk '{print $2}')
success "RQLite v$INSTALLED_VERSION installed successfully"
else
error "RQLite installation failed"
exit 1
fi
} }
# Check port availability # Check port availability
@ -382,18 +174,6 @@ configuration_wizard() {
log "${GREEN} DeBros Network Configuration Wizard ${NOCOLOR}" log "${GREEN} DeBros Network Configuration Wizard ${NOCOLOR}"
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
if [ "$NON_INTERACTIVE" = true ]; then
log "Non-interactive mode: using default configuration"
NODE_TYPE="bootstrap"
SOLANA_WALLET="11111111111111111111111111111111" # Placeholder wallet
CONFIGURE_FIREWALL="yes"
log "Node Type: $NODE_TYPE"
log "Installation Directory: $INSTALL_DIR"
log "Firewall Configuration: $CONFIGURE_FIREWALL"
success "Configuration completed with defaults"
return 0
fi
# Node type selection # Node type selection
while true; do while true; do
echo -e "${GREEN}Select node type:${NOCOLOR}" echo -e "${GREEN}Select node type:${NOCOLOR}"
@ -448,8 +228,6 @@ setup_directories() {
if ! id "debros" &>/dev/null; then if ! id "debros" &>/dev/null; then
sudo useradd -r -s /bin/false -d "$INSTALL_DIR" debros sudo useradd -r -s /bin/false -d "$INSTALL_DIR" debros
log "Created debros user" log "Created debros user"
else
log "User 'debros' already exists"
fi fi
# Create directory structure # Create directory structure
@ -457,19 +235,13 @@ setup_directories() {
sudo mkdir -p "$INSTALL_DIR/keys/$NODE_TYPE" sudo mkdir -p "$INSTALL_DIR/keys/$NODE_TYPE"
sudo mkdir -p "$INSTALL_DIR/data/$NODE_TYPE"/{rqlite,storage} sudo mkdir -p "$INSTALL_DIR/data/$NODE_TYPE"/{rqlite,storage}
# Set ownership first, then permissions # Set ownership and permissions
sudo chown -R debros:debros "$INSTALL_DIR" 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"
sudo chmod 700 "$INSTALL_DIR/keys/$NODE_TYPE" sudo chmod 600 "$INSTALL_DIR/keys/$NODE_TYPE" 2>/dev/null || true
# Ensure the debros user can write to the keys directory success "Directory structure created"
sudo chmod 755 "$INSTALL_DIR/data"
sudo chmod 755 "$INSTALL_DIR/logs"
sudo chmod 755 "$INSTALL_DIR/configs"
sudo chmod 755 "$INSTALL_DIR/bin"
success "Directory structure ready"
} }
# Clone or update repository # Clone or update repository
@ -491,30 +263,16 @@ setup_source_code() {
# Generate identity key # Generate identity key
generate_identity() { generate_identity() {
local identity_file="$INSTALL_DIR/keys/$NODE_TYPE/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..." log "Generating node identity..."
cd "$INSTALL_DIR/src" cd "$INSTALL_DIR/src"
# Create a custom identity generation script with output path support # Create a temporary Go program for key generation
cat > /tmp/generate_identity_custom.go << 'EOF' cat > /tmp/generate_identity.go << 'EOF'
package main package main
import ( import (
"crypto/rand" "crypto/rand"
"flag"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
@ -524,15 +282,13 @@ import (
) )
func main() { func main() {
var outputPath string if len(os.Args) != 2 {
flag.StringVar(&outputPath, "output", "", "Output path for identity key") fmt.Println("Usage: go run generate_identity.go <key_file_path>")
flag.Parse()
if outputPath == "" {
fmt.Println("Usage: go run generate_identity_custom.go -output <path>")
os.Exit(1) os.Exit(1)
} }
keyFile := os.Args[1]
// Generate identity // Generate identity
priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, rand.Reader) priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Ed25519, 2048, rand.Reader)
if err != nil { if err != nil {
@ -552,24 +308,23 @@ func main() {
} }
// Create directory // Create directory
if err := os.MkdirAll(filepath.Dir(outputPath), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(keyFile), 0700); err != nil {
panic(err) panic(err)
} }
// Save identity // Save identity
if err := os.WriteFile(outputPath, data, 0600); err != nil { if err := os.WriteFile(keyFile, data, 0600); err != nil {
panic(err) panic(err)
} }
fmt.Printf("Generated Peer ID: %s\n", peerID.String()) fmt.Printf("Generated Peer ID: %s\n", peerID.String())
fmt.Printf("Identity saved to: %s\n", outputPath) fmt.Printf("Identity saved to: %s\n", keyFile)
} }
EOF EOF
# Ensure Go is in PATH and generate the identity key # Generate the identity key
export PATH=$PATH:/usr/local/go/bin sudo -u debros go run /tmp/generate_identity.go "$INSTALL_DIR/keys/$NODE_TYPE/identity.key"
sudo -u debros env "PATH=$PATH:/usr/local/go/bin" "GOMOD=$(pwd)" go run /tmp/generate_identity_custom.go -output "$identity_file" rm /tmp/generate_identity.go
rm /tmp/generate_identity_custom.go
success "Node identity generated" success "Node identity generated"
} }
@ -580,9 +335,8 @@ build_binaries() {
cd "$INSTALL_DIR/src" cd "$INSTALL_DIR/src"
# Ensure Go is in PATH and build all binaries # Build all binaries
export PATH=$PATH:/usr/local/go/bin sudo -u debros make build
sudo -u debros env "PATH=$PATH:/usr/local/go/bin" make build
# Copy binaries to installation directory # Copy binaries to installation directory
sudo cp bin/* "$INSTALL_DIR/bin/" sudo cp bin/* "$INSTALL_DIR/bin/"
@ -640,85 +394,35 @@ EOF
# Configure firewall # Configure firewall
configure_firewall() { configure_firewall() {
if [[ "$CONFIGURE_FIREWALL" == "yes" ]]; then if [[ "$CONFIGURE_FIREWALL" == "yes" ]]; then
log "Configuring firewall rules..." log "Configuring firewall..."
if command -v ufw &> /dev/null; then if command -v ufw &> /dev/null; then
# Add firewall rules regardless of UFW status
# This allows the rules to be ready when UFW is enabled
log "Adding UFW rules for DeBros Network ports..."
# Add ports based on node type with error handling
if [ "$NODE_TYPE" = "bootstrap" ]; then if [ "$NODE_TYPE" = "bootstrap" ]; then
for port in $BOOTSTRAP_PORT $RQLITE_BOOTSTRAP_PORT $RAFT_BOOTSTRAP_PORT; do sudo ufw allow $BOOTSTRAP_PORT
if ! sudo ufw allow $port; then sudo ufw allow $RQLITE_BOOTSTRAP_PORT
error "Failed to allow port $port" sudo ufw allow $RAFT_BOOTSTRAP_PORT
exit 1
fi
log "Added UFW rule: allow port $port"
done
else else
for port in $NODE_PORT $RQLITE_NODE_PORT $RAFT_NODE_PORT; do sudo ufw allow $NODE_PORT
if ! sudo ufw allow $port; then sudo ufw allow $RQLITE_NODE_PORT
error "Failed to allow port $port" sudo ufw allow $RAFT_NODE_PORT
exit 1
fi
log "Added UFW rule: allow port $port"
done
fi fi
# Check UFW status and inform user # Enable ufw if not already active
UFW_STATUS=$(sudo ufw status | grep -o "Status: [a-z]\+" | awk '{print $2}' || echo "inactive") UFW_STATUS=$(sudo ufw status | grep -o "Status: [a-z]*" | awk '{print $2}' || echo "inactive")
if [[ "$UFW_STATUS" != "active" ]]; then
if [[ "$UFW_STATUS" == "active" ]]; then echo "y" | sudo ufw enable
success "Firewall rules added and active"
else
success "Firewall rules added (UFW is inactive - rules will take effect when UFW is enabled)"
log "To enable UFW with current rules: sudo ufw enable"
fi fi
success "Firewall configured"
else else
warning "UFW not found. Please configure firewall manually." warning "UFW not found. Please configure firewall manually."
log "Required ports to allow:"
if [ "$NODE_TYPE" = "bootstrap" ]; then
log " - Port $BOOTSTRAP_PORT (Bootstrap)"
log " - Port $RQLITE_BOOTSTRAP_PORT (RQLite)"
log " - Port $RAFT_BOOTSTRAP_PORT (Raft)"
else
log " - Port $NODE_PORT (Node)"
log " - Port $RQLITE_NODE_PORT (RQLite)"
log " - Port $RAFT_NODE_PORT (Raft)"
fi
fi fi
fi fi
} }
# Create systemd service # Create systemd service
create_systemd_service() { create_systemd_service() {
local service_file="/etc/systemd/system/debros-$NODE_TYPE.service" log "Creating systemd service..."
# Always clean up any existing service files to ensure fresh start
for service in debros-bootstrap debros-node; do
if [ -f "/etc/systemd/system/$service.service" ]; then
log "Cleaning up existing $service service..."
sudo systemctl stop $service.service 2>/dev/null || true
sudo systemctl disable $service.service 2>/dev/null || true
sudo rm -f /etc/systemd/system/$service.service
fi
done
sudo systemctl daemon-reload
log "Creating new systemd service..."
# Determine the correct ExecStart command based on node type
local exec_start=""
if [ "$NODE_TYPE" = "bootstrap" ]; then
exec_start="$INSTALL_DIR/bin/bootstrap -data $INSTALL_DIR/data/bootstrap -port $BOOTSTRAP_PORT"
else
# For regular nodes, we need to specify the bootstrap peer
# This should be configured based on the bootstrap node's address
exec_start="$INSTALL_DIR/bin/node -data $INSTALL_DIR/data/node -port $NODE_PORT"
# Note: Bootstrap peer address would need to be configured separately
# exec_start="$INSTALL_DIR/bin/node -data $INSTALL_DIR/data/node -port $NODE_PORT -bootstrap /ip4/BOOTSTRAP_IP/tcp/$BOOTSTRAP_PORT/p2p/BOOTSTRAP_PEER_ID"
fi
cat > /tmp/debros-$NODE_TYPE.service << EOF cat > /tmp/debros-$NODE_TYPE.service << EOF
[Unit] [Unit]
@ -731,7 +435,7 @@ Type=simple
User=debros User=debros
Group=debros Group=debros
WorkingDirectory=$INSTALL_DIR WorkingDirectory=$INSTALL_DIR
ExecStart=$exec_start ExecStart=$INSTALL_DIR/bin/$NODE_TYPE -config $INSTALL_DIR/configs/$NODE_TYPE.yaml
Restart=always Restart=always
RestartSec=10 RestartSec=10
StandardOutput=journal StandardOutput=journal
@ -749,11 +453,11 @@ ReadWritePaths=$INSTALL_DIR
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
sudo mv /tmp/debros-$NODE_TYPE.service "$service_file" sudo mv /tmp/debros-$NODE_TYPE.service /etc/systemd/system/
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable debros-$NODE_TYPE.service sudo systemctl enable debros-$NODE_TYPE.service
success "Systemd service ready" success "Systemd service created and enabled"
} }
# Start the service # Start the service
@ -794,7 +498,6 @@ main() {
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
detect_os detect_os
check_existing_installation
check_ports check_ports
# Check and install Go if needed # Check and install Go if needed
@ -803,48 +506,19 @@ main() {
fi fi
install_dependencies install_dependencies
install_rqlite configuration_wizard
# Skip configuration wizard in update mode
if [ "$UPDATE_MODE" != true ]; then
configuration_wizard
else
log "Update mode: skipping configuration wizard"
# Detect existing node type
if [ -f "$INSTALL_DIR/configs/bootstrap.yaml" ]; then
NODE_TYPE="bootstrap"
elif [ -f "$INSTALL_DIR/configs/node.yaml" ]; then
NODE_TYPE="node"
else
error "Cannot determine existing node type"
exit 1
fi
log "Detected existing node type: $NODE_TYPE"
fi
setup_directories setup_directories
setup_source_code setup_source_code
generate_identity generate_identity
build_binaries build_binaries
generate_configs
# Only generate new configs if not in update mode configure_firewall
if [ "$UPDATE_MODE" != true ]; then
generate_configs
configure_firewall
else
log "Update mode: keeping existing configuration"
fi
create_systemd_service create_systemd_service
start_service start_service
# Display completion information # Display completion information
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
if [ "$UPDATE_MODE" = true ]; then log "${GREEN} Installation Complete! ${NOCOLOR}"
log "${GREEN} Update Complete! ${NOCOLOR}"
else
log "${GREEN} Installation Complete! ${NOCOLOR}"
fi
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
log "${GREEN}Node Type:${NOCOLOR} ${CYAN}$NODE_TYPE${NOCOLOR}" log "${GREEN}Node Type:${NOCOLOR} ${CYAN}$NODE_TYPE${NOCOLOR}"
@ -869,14 +543,10 @@ main() {
log "${CYAN} - sudo systemctl stop debros-$NODE_TYPE${NOCOLOR} (Stop service)" log "${CYAN} - sudo systemctl stop debros-$NODE_TYPE${NOCOLOR} (Stop service)"
log "${CYAN} - sudo systemctl start debros-$NODE_TYPE${NOCOLOR} (Start service)" log "${CYAN} - sudo systemctl start debros-$NODE_TYPE${NOCOLOR} (Start service)"
log "${CYAN} - sudo journalctl -u debros-$NODE_TYPE.service -f${NOCOLOR} (View logs)" log "${CYAN} - sudo journalctl -u debros-$NODE_TYPE.service -f${NOCOLOR} (View logs)"
log "${CYAN} - $INSTALL_DIR/bin/network-cli${NOCOLOR} (Use CLI tools)" log "${CYAN} - $INSTALL_DIR/bin/cli${NOCOLOR} (Use CLI tools)"
log "${BLUE}==================================================${NOCOLOR}" log "${BLUE}==================================================${NOCOLOR}"
if [ "$UPDATE_MODE" = true ]; then success "DeBros Network $NODE_TYPE node is now running!"
success "DeBros Network $NODE_TYPE node has been updated and is running!"
else
success "DeBros Network $NODE_TYPE node is now running!"
fi
log "${CYAN}For documentation visit: https://docs.debros.io${NOCOLOR}" log "${CYAN}For documentation visit: https://docs.debros.io${NOCOLOR}"
} }