diff --git a/CHANGELOG.md b/CHANGELOG.md index cf3e7c4..82534f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,28 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant ### Security +## [0.44.0] - 2025-09-25 + +### Added + +- Added gateway.yaml file for gateway default configurations + +### Changed + +- Updated readme to include all options for .yaml files + +### Deprecated + +### Removed + +- Removed unused command setup-production-security.sh +- Removed anyone proxy from libp2p proxy + +### Fixed + +### Security + + ## [0.43.6] - 2025-09-20 ### Added diff --git a/Makefile b/Makefile index e0fe496..e3a5b18 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ test-e2e: .PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports -VERSION := 0.43.6-beta +VERSION := 0.44.0-beta COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)' diff --git a/README.md b/README.md index e5c1d57..7eabb77 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,6 @@ node: - "/ip4/0.0.0.0/tcp/4001" data_dir: "./data/bootstrap" max_connections: 100 - disable_anonrc: true database: data_dir: "./data/db" @@ -224,7 +223,6 @@ node: - "/ip4/0.0.0.0/tcp/4002" data_dir: "./data/node2" max_connections: 50 - disable_anonrc: true database: data_dir: "./data/db" @@ -255,11 +253,118 @@ logging: output_file: "" ``` +### YAML Reference + +#### Node YAML (configs/node.yaml or configs/bootstrap.yaml) + +The .yaml files are required in order for the nodes and the gateway to run correctly. + +node: +- id (string) Optional node ID. Auto-generated if empty. +- type (string) "bootstrap" or "node". Default: "node". +- listen_addresses (string[]) LibP2P listen multiaddrs. Default: ["/ip4/0.0.0.0/tcp/4001"]. +- data_dir (string) Data directory. Default: "./data". +- max_connections (int) Max peer connections. Default: 50. + +database: +- data_dir (string) Directory for database files. Default: "./data/db". +- replication_factor (int) Number of replicas. Default: 3. +- shard_count (int) Shards for data distribution. Default: 16. +- max_database_size (int64 bytes) Max DB size. Default: 1073741824 (1GB). +- backup_interval (duration) e.g., "24h". Default: 24h. +- rqlite_port (int) RQLite HTTP API port. Default: 5001. +- rqlite_raft_port (int) RQLite Raft port. Default: 7001. +- rqlite_join_address (string) HTTP address of an existing RQLite node to join. Empty for bootstrap. + +discovery: +- bootstrap_peers (string[]) List of LibP2P multiaddrs of bootstrap peers. +- discovery_interval (duration) How often to announce/discover peers. Default: 15s. +- bootstrap_port (int) Default port for bootstrap nodes. Default: 4001. +- http_adv_address (string) Advertised HTTP address for RQLite (host:port). +- raft_adv_address (string) Advertised Raft address (host:port). +- node_namespace (string) Namespace for node identifiers. Default: "default". + +security: +- enable_tls (bool) Enable TLS for externally exposed services. Default: false. +- private_key_file (string) Path to TLS private key (if TLS enabled). +- certificate_file (string) Path to TLS certificate (if TLS enabled). + +logging: +- level (string) one of "debug", "info", "warn", "error". Default: "info". +- format (string) "json" or "console". Default: "console". +- output_file (string) Empty for stdout; otherwise path to log file. + +Precedence (node): Flags > YAML > Defaults. + +Example node.yaml + +```yaml +node: + id: "node2" + listen_addresses: + - "/ip4/0.0.0.0/tcp/4002" + data_dir: "./data/node2" + max_connections: 50 + disable_anonrc: true + +database: + data_dir: "./data/db" + replication_factor: 3 + shard_count: 16 + max_database_size: 1073741824 + backup_interval: 24h + rqlite_port: 5001 + rqlite_raft_port: 7001 + rqlite_join_address: "http://127.0.0.1:5001" + +discovery: + bootstrap_peers: + - "" + discovery_interval: 15s + bootstrap_port: 4001 + http_adv_address: "127.0.0.1" + raft_adv_address: "" + node_namespace: "default" + +security: + enable_tls: false + private_key_file: "" + certificate_file: "" + auth_enabled: false + +logging: + level: "info" + format: "console" + output_file: "" +``` + +#### Gateway YAML (configs/gateway.yaml) + +- listen_addr (string) HTTP listen address, e.g., ":6001". Default: ":6001". +- client_namespace (string) Namespace used by the gateway client. Default: "default". +- bootstrap_peers (string[]) List of bootstrap peer multiaddrs. Default: empty. + +Precedence (gateway): Flags > Environment Variables > YAML > Defaults. +Environment variables: +- GATEWAY_ADDR +- GATEWAY_NAMESPACE +- GATEWAY_BOOTSTRAP_PEERS (comma-separated) + +Example gateway.yaml + +```yaml +listen_addr: ":6001" +client_namespace: "default" +bootstrap_peers: + - "" +``` + ### Flags & Environment Variables - **Flags**: Override config at startup (`--data`, `--p2p-port`, `--rqlite-http-port`, etc.) - **Env Vars**: Override config and flags (`NODE_ID`, `RQLITE_PORT`, `BOOTSTRAP_PEERS`, etc.) -- **Precedence**: Flags > Env Vars > YAML > Defaults +- **Precedence (gateway)**: Flags > Env Vars > YAML > Defaults +- **Precedence (node)**: Flags > YAML > Defaults ### Bootstrap & Database Endpoints @@ -303,7 +408,6 @@ logging: --timeout 30s # Set operation timeout --bootstrap # Override bootstrap peer --production # Use production bootstrap peers ---disable-anonrc # Disable anonymous routing (Tor/SOCKS5) ``` ### Database Operations (Gateway REST) @@ -375,7 +479,7 @@ go run ./cmd/gateway ### Configuration -The gateway can be configured via environment variables: +The gateway can be configured via configs/gateway.yaml and environment variables (env override YAML): ```bash # Basic Configuration diff --git a/cmd/cli/main.go b/cmd/cli/main.go index cc9e009..c3fd8a6 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -12,7 +12,6 @@ import ( "strings" "time" - "github.com/DeBrosOfficial/network/pkg/anyoneproxy" "github.com/DeBrosOfficial/network/pkg/auth" "github.com/DeBrosOfficial/network/pkg/client" "github.com/libp2p/go-libp2p/core/crypto" @@ -24,7 +23,6 @@ var ( timeout = 30 * time.Second format = "table" useProduction = false - disableAnon = false ) // version metadata populated via -ldflags at build time @@ -46,9 +44,6 @@ func main() { // Parse global flags parseGlobalFlags(args) - // Apply disable flag early so all network operations honor it - anyoneproxy.SetDisabled(disableAnon) - switch command { case "version": fmt.Printf("network-cli %s", version) @@ -111,8 +106,6 @@ func parseGlobalFlags(args []string) { } case "--production": useProduction = true - case "--disable-anonrc": - disableAnon = true } } } diff --git a/cmd/gateway/config.go b/cmd/gateway/config.go index 6b03c20..cc8f345 100644 --- a/cmd/gateway/config.go +++ b/cmd/gateway/config.go @@ -8,6 +8,7 @@ import ( "github.com/DeBrosOfficial/network/pkg/gateway" "github.com/DeBrosOfficial/network/pkg/logging" "go.uber.org/zap" + "gopkg.in/yaml.v3" ) // For transition, alias main.GatewayConfig to pkg/gateway.Config @@ -36,36 +37,101 @@ func getEnvBoolDefault(key string, def bool) bool { } } -// parseGatewayConfig parses flags and environment variables into GatewayConfig. -// Priority: flags > env > defaults. +// parseGatewayConfig loads optional configs/gateway.yaml then applies env and flags. +// Priority: flags > env > yaml > defaults. func parseGatewayConfig(logger *logging.ColoredLogger) *gateway.Config { - addr := flag.String("addr", getEnvDefault("GATEWAY_ADDR", ":6001"), "HTTP listen address (e.g., :6001)") - ns := flag.String("namespace", getEnvDefault("GATEWAY_NAMESPACE", "default"), "Client namespace for scoping resources") - peers := flag.String("bootstrap-peers", getEnvDefault("GATEWAY_BOOTSTRAP_PEERS", ""), "Comma-separated bootstrap peers for network client") + // Base defaults + cfg := &gateway.Config{ + ListenAddr: ":6001", + ClientNamespace: "default", + BootstrapPeers: nil, + } - // Do not call flag.Parse() elsewhere to avoid double-parsing - flag.Parse() - - var bootstrap []string - if p := strings.TrimSpace(*peers); p != "" { - parts := strings.Split(p, ",") - for _, part := range parts { - val := strings.TrimSpace(part) - if val != "" { - bootstrap = append(bootstrap, val) + // 1) YAML (optional) + { + type yamlCfg struct { + ListenAddr string `yaml:"listen_addr"` + ClientNamespace string `yaml:"client_namespace"` + BootstrapPeers []string `yaml:"bootstrap_peers"` + } + const path = "configs/gateway.yaml" + if data, err := os.ReadFile(path); err == nil { + var y yamlCfg + if err := yaml.Unmarshal(data, &y); err != nil { + logger.ComponentWarn(logging.ComponentGeneral, "failed to parse configs/gateway.yaml; ignoring", zap.Error(err)) + } else { + if v := strings.TrimSpace(y.ListenAddr); v != "" { + cfg.ListenAddr = v + } + if v := strings.TrimSpace(y.ClientNamespace); v != "" { + cfg.ClientNamespace = v + } + if len(y.BootstrapPeers) > 0 { + var bp []string + for _, p := range y.BootstrapPeers { + p = strings.TrimSpace(p) + if p != "" { + bp = append(bp, p) + } + } + if len(bp) > 0 { + cfg.BootstrapPeers = bp + } + } } } } + // 2) Env overrides + if v := strings.TrimSpace(os.Getenv("GATEWAY_ADDR")); v != "" { + cfg.ListenAddr = v + } + if v := strings.TrimSpace(os.Getenv("GATEWAY_NAMESPACE")); v != "" { + cfg.ClientNamespace = v + } + if v := strings.TrimSpace(os.Getenv("GATEWAY_BOOTSTRAP_PEERS")); v != "" { + parts := strings.Split(v, ",") + var bp []string + for _, part := range parts { + s := strings.TrimSpace(part) + if s != "" { + bp = append(bp, s) + } + } + cfg.BootstrapPeers = bp + } + + // 3) Flags (override env) + addr := flag.String("addr", "", "HTTP listen address (e.g., :6001)") + ns := flag.String("namespace", "", "Client namespace for scoping resources") + peers := flag.String("bootstrap-peers", "", "Comma-separated bootstrap peers for network client") + + // Do not call flag.Parse() elsewhere to avoid double-parsing + flag.Parse() + + if a := strings.TrimSpace(*addr); a != "" { + cfg.ListenAddr = a + } + if n := strings.TrimSpace(*ns); n != "" { + cfg.ClientNamespace = n + } + if p := strings.TrimSpace(*peers); p != "" { + parts := strings.Split(p, ",") + var bp []string + for _, part := range parts { + s := strings.TrimSpace(part) + if s != "" { + bp = append(bp, s) + } + } + cfg.BootstrapPeers = bp + } + logger.ComponentInfo(logging.ComponentGeneral, "Loaded gateway configuration", - zap.String("addr", *addr), - zap.String("namespace", *ns), - zap.Int("bootstrap_peer_count", len(bootstrap)), + zap.String("addr", cfg.ListenAddr), + zap.String("namespace", cfg.ClientNamespace), + zap.Int("bootstrap_peer_count", len(cfg.BootstrapPeers)), ) - return &gateway.Config{ - ListenAddr: *addr, - ClientNamespace: *ns, - BootstrapPeers: bootstrap, - } + return cfg } diff --git a/cmd/node/main.go b/cmd/node/main.go index 7eea3d4..53fb562 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -11,7 +11,6 @@ import ( "path/filepath" "syscall" - "github.com/DeBrosOfficial/network/pkg/anyoneproxy" "github.com/DeBrosOfficial/network/pkg/config" "github.com/DeBrosOfficial/network/pkg/logging" "github.com/DeBrosOfficial/network/pkg/node" @@ -32,7 +31,7 @@ func setup_logger(component logging.Component) (logger *logging.ColoredLogger) { } // parse_and_return_network_flags it initializes all the network flags coming from the .yaml files -func parse_and_return_network_flags() (configPath *string, dataDir, nodeID *string, p2pPort, rqlHTTP, rqlRaft *int, disableAnon *bool, rqlJoinAddr *string, advAddr *string, help *bool) { +func parse_and_return_network_flags() (configPath *string, dataDir, nodeID *string, p2pPort, rqlHTTP, rqlRaft *int, rqlJoinAddr *string, advAddr *string, help *bool) { logger := setup_logger(logging.ComponentNode) configPath = flag.String("config", "", "Path to config YAML file (overrides defaults)") @@ -41,7 +40,6 @@ func parse_and_return_network_flags() (configPath *string, dataDir, nodeID *stri p2pPort = flag.Int("p2p-port", 4001, "LibP2P listen port") rqlHTTP = flag.Int("rqlite-http-port", 5001, "RQLite HTTP API port") rqlRaft = flag.Int("rqlite-raft-port", 7001, "RQLite Raft port") - disableAnon = flag.Bool("disable-anonrc", false, "Disable Anyone proxy routing (defaults to enabled on 127.0.0.1:9050)") rqlJoinAddr = flag.String("rqlite-join-address", "", "RQLite address to join (e.g., /ip4/)") advAddr = flag.String("adv-addr", "127.0.0.1", "Default Advertise address for rqlite and rafts") help = flag.Bool("help", false, "Show help") @@ -78,7 +76,6 @@ func parse_and_return_network_flags() (configPath *string, dataDir, nodeID *stri &p2pPortVal, &cfg.Database.RQLitePort, &cfg.Database.RQLiteRaftPort, - &cfg.Node.DisableAnonRC, &cfg.Database.RQLiteJoinAddress, &cfg.Discovery.HttpAdvAddress, help @@ -100,19 +97,6 @@ func LoadConfigFromYAML(path string) (*config.Config, error) { return &cfg, nil } -// disable_anon_proxy disables the anonymous proxy routing, by default on development -// it is not suggested to run anyone proxy -func disable_anon_proxy(disableAnon *bool) bool { - anyoneproxy.SetDisabled(*disableAnon) - logger := setup_logger(logging.ComponentAnyone) - - if *disableAnon { - logger.Info("Anyone proxy routing is disabled. This means the node will not use the default Tor proxy for anonymous routing.\n") - } - - return true -} - // check_if_should_open_help checks if the help flag is set and opens the help if it is func check_if_should_open_help(help *bool) { if *help { @@ -209,9 +193,8 @@ func load_args_into_config(cfg *config.Config, p2pPort, rqlHTTP, rqlRaft *int, r func main() { logger := setup_logger(logging.ComponentNode) - _, dataDir, nodeID, p2pPort, rqlHTTP, rqlRaft, disableAnon, rqlJoinAddr, advAddr, help := parse_and_return_network_flags() + _, dataDir, nodeID, p2pPort, rqlHTTP, rqlRaft, rqlJoinAddr, advAddr, help := parse_and_return_network_flags() - disable_anon_proxy(disableAnon) check_if_should_open_help(help) select_data_dir(dataDir, nodeID) diff --git a/pkg/client/client.go b/pkg/client/client.go index 79a8bcd..1f3938d 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -13,14 +13,12 @@ import ( "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/security/noise" - libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/multiformats/go-multiaddr" "go.uber.org/zap" libp2ppubsub "github.com/libp2p/go-libp2p-pubsub" - "github.com/DeBrosOfficial/network/pkg/anyoneproxy" "github.com/DeBrosOfficial/network/pkg/pubsub" ) @@ -131,15 +129,8 @@ func (c *Client) Connect() error { libp2p.Security(noise.ID, noise.New), libp2p.DefaultMuxers, ) - if anyoneproxy.Enabled() { - opts = append(opts, libp2p.Transport(tcp.NewTCPTransport, tcp.WithDialerForAddr(anyoneproxy.DialerForAddr()))) - } else { - opts = append(opts, libp2p.Transport(tcp.NewTCPTransport)) - } + opts = append(opts, libp2p.Transport(tcp.NewTCPTransport)) // Enable QUIC only when not proxying. When proxy is enabled, prefer TCP via SOCKS5. - if !anyoneproxy.Enabled() { - opts = append(opts, libp2p.Transport(libp2pquic.NewTransport)) - } h, err := libp2p.New(opts...) if err != nil { return fmt.Errorf("failed to create libp2p host: %w", err) diff --git a/pkg/client/implementations.go b/pkg/client/implementations.go index bf1bc9d..ea06381 100644 --- a/pkg/client/implementations.go +++ b/pkg/client/implementations.go @@ -7,7 +7,6 @@ import ( "sync" "time" - "github.com/DeBrosOfficial/network/pkg/anyoneproxy" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/rqlite/gorqlite" @@ -214,13 +213,8 @@ func (d *DatabaseClientImpl) connectToAvailableNode() (*gorqlite.Connection, err for _, rqliteURL := range rqliteNodes { var conn *gorqlite.Connection var err error - // If Anyone proxy is enabled, build a proxy-aware HTTP client - if anyoneproxy.Enabled() { - httpClient := anyoneproxy.NewHTTPClient() - conn, err = gorqlite.OpenWithClient(rqliteURL, httpClient) - } else { - conn, err = gorqlite.Open(rqliteURL) - } + + conn, err = gorqlite.Open(rqliteURL) if err != nil { lastErr = err continue diff --git a/pkg/config/config.go b/pkg/config/config.go index 568feb7..de0bcbe 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -22,7 +22,6 @@ type NodeConfig struct { ListenAddresses []string `yaml:"listen_addresses"` // LibP2P listen addresses DataDir string `yaml:"data_dir"` // Data directory MaxConnections int `yaml:"max_connections"` // Maximum peer connections - DisableAnonRC bool `yaml:"disable_anon_rc"` // Disable Anyone proxy/SOCKS5 } // DatabaseConfig contains database-related configuration @@ -110,11 +109,12 @@ func DefaultConfig() *Config { }, Discovery: DiscoveryConfig{ BootstrapPeers: []string{ - "/ip4/217.76.54.168/tcp/4001/p2p/12D3KooWDp7xeShVY9uHfqNVPSsJeCKUatAviFZV8Y1joox5nUvx", - "/ip4/217.76.54.178/tcp/4001/p2p/12D3KooWKZnirPwNT4URtNSWK45f6vLkEs4xyUZ792F8Uj1oYnm1", - "/ip4/51.83.128.181/tcp/4001/p2p/12D3KooWBn2Zf1R8v9pEfmz7hDZ5b3oADxfejA3zJBYzKRCzgvhR", - "/ip4/155.133.27.199/tcp/4001/p2p/12D3KooWC69SBzM5QUgrLrfLWUykE8au32X5LwT7zwv9bixrQPm1", - "/ip4/217.76.56.2/tcp/4001/p2p/12D3KooWEiqJHvznxqJ5p2y8mUs6Ky6dfU1xTYFQbyKRCABfcZz4", + "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWSHHwEY6cga3ng7tD1rzStAU58ogQXVMX3LZJ6Gqf6dee", + // "/ip4/217.76.54.168/tcp/4001/p2p/12D3KooWDp7xeShVY9uHfqNVPSsJeCKUatAviFZV8Y1joox5nUvx", + // "/ip4/217.76.54.178/tcp/4001/p2p/12D3KooWKZnirPwNT4URtNSWK45f6vLkEs4xyUZ792F8Uj1oYnm1", + // "/ip4/51.83.128.181/tcp/4001/p2p/12D3KooWBn2Zf1R8v9pEfmz7hDZ5b3oADxfejA3zJBYzKRCzgvhR", + // "/ip4/155.133.27.199/tcp/4001/p2p/12D3KooWC69SBzM5QUgrLrfLWUykE8au32X5LwT7zwv9bixrQPm1", + // "/ip4/217.76.56.2/tcp/4001/p2p/12D3KooWEiqJHvznxqJ5p2y8mUs6Ky6dfU1xTYFQbyKRCABfcZz4", }, BootstrapPort: 4001, // Default LibP2P port DiscoveryInterval: time.Second * 15, // Back to 15 seconds for testing diff --git a/pkg/node/node.go b/pkg/node/node.go index e6c45f2..b41feca 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -22,7 +22,6 @@ import ( "github.com/multiformats/go-multiaddr" "go.uber.org/zap" - "github.com/DeBrosOfficial/network/pkg/anyoneproxy" "github.com/DeBrosOfficial/network/pkg/config" "github.com/DeBrosOfficial/network/pkg/database" "github.com/DeBrosOfficial/network/pkg/logging" @@ -223,18 +222,6 @@ func (n *Node) startLibP2P() error { return fmt.Errorf("failed to load identity: %w", err) } - // Log Anyone proxy status before constructing host - n.logger.ComponentInfo(logging.ComponentLibP2P, "Anyone proxy status", - zap.Bool("proxy_enabled", anyoneproxy.Enabled()), - zap.String("proxy_addr", anyoneproxy.Address()), - zap.Bool("proxy_running", anyoneproxy.Running()), - ) - - if anyoneproxy.Enabled() && !anyoneproxy.Running() { - n.logger.Warn("Anyone proxy is enabled but not reachable", - zap.String("addr", anyoneproxy.Address())) - } - // Create LibP2P host with persistent identity // Build options allowing conditional proxying via Anyone SOCKS5 var opts []libp2p.Option @@ -246,11 +233,7 @@ func (n *Node) startLibP2P() error { ) // TCP transport with optional SOCKS5 dialer override - if anyoneproxy.Enabled() { - opts = append(opts, libp2p.Transport(tcp.NewTCPTransport, tcp.WithDialerForAddr(anyoneproxy.DialerForAddr()))) - } else { - opts = append(opts, libp2p.Transport(tcp.NewTCPTransport)) - } + opts = append(opts, libp2p.Transport(tcp.NewTCPTransport)) h, err := libp2p.New(opts...) if err != nil { diff --git a/scripts/setup-production-security.sh b/scripts/setup-production-security.sh deleted file mode 100755 index 10e5c0b..0000000 --- a/scripts/setup-production-security.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# DeBros Network Production Security Setup -# This script configures secure RQLite clustering with authentication - -DEBROS_DIR="/opt/debros" -CONFIG_DIR="$DEBROS_DIR/configs" -KEYS_DIR="$DEBROS_DIR/keys" - -echo "🔐 Setting up DeBros Network Production Security..." - -# Create security directories -sudo mkdir -p "$CONFIG_DIR" "$KEYS_DIR" -sudo chown debros:debros "$CONFIG_DIR" "$KEYS_DIR" -sudo chmod 750 "$KEYS_DIR" - -# Generate cluster authentication credentials -CLUSTER_USER="debros_cluster" -CLUSTER_PASS=$(openssl rand -base64 32) -API_USER="debros_api" -API_PASS=$(openssl rand -base64 32) - -echo "🔑 Generated cluster credentials:" -echo " Cluster User: $CLUSTER_USER" -echo " API User: $API_USER" - -# Create RQLite users configuration -cat > "$CONFIG_DIR/rqlite-users.json" << EOF -[ - { - "username": "$CLUSTER_USER", - "password": "$CLUSTER_PASS", - "perms": ["*"] - }, - { - "username": "$API_USER", - "password": "$API_PASS", - "perms": ["status", "ready", "nodes", "db:*"] - } -] -EOF - -sudo chown debros:debros "$CONFIG_DIR/rqlite-users.json" -sudo chmod 600 "$CONFIG_DIR/rqlite-users.json" - -# Store credentials securely -cat > "$KEYS_DIR/rqlite-cluster-auth" << EOF -RQLITE_CLUSTER_USER="$CLUSTER_USER" -RQLITE_CLUSTER_PASS="$CLUSTER_PASS" -RQLITE_API_USER="$API_USER" -RQLITE_API_PASS="$API_PASS" -EOF - -sudo chown debros:debros "$KEYS_DIR/rqlite-cluster-auth" -sudo chmod 600 "$KEYS_DIR/rqlite-cluster-auth" - -# Configure firewall for production -echo "🛡️ Configuring production firewall rules..." - -# Reset UFW to defaults -sudo ufw --force reset - -# Default policies -sudo ufw default deny incoming -sudo ufw default allow outgoing - -# SSH (adjust port as needed) -sudo ufw allow 22/tcp comment "SSH" - -# LibP2P P2P networking (public, encrypted) -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 5001 comment "RQLite HTTP from $ip" - sudo ufw allow from "$ip" to any port 7001 comment "RQLite Raft from $ip" -done - -# Enable firewall -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:5001" - -# Create environment file for authenticated connections -cat > "$CONFIG_DIR/rqlite-env" << EOF -# RQLite cluster authentication -RQLITE_JOIN_AUTH_USER="$CLUSTER_USER" -RQLITE_JOIN_AUTH_PASS="$CLUSTER_PASS" -RQLITE_JOIN_ADDRESS_AUTH="$AUTHENTICATED_JOIN_ADDRESS" -EOF - -sudo chown debros:debros "$CONFIG_DIR/rqlite-env" -sudo chmod 600 "$CONFIG_DIR/rqlite-env" - -# Create connection helper script -cat > "$DEBROS_DIR/bin/rqlite-connect" << 'EOF' -#!/bin/bash -# Helper script for authenticated RQLite connections - -source /opt/debros/keys/rqlite-cluster-auth - -if [ "$1" = "cluster" ]; then - rqlite -H localhost -p 5001 -u "$RQLITE_CLUSTER_USER" -p "$RQLITE_CLUSTER_PASS" -elif [ "$1" = "api" ]; then - rqlite -H localhost -p 5001 -u "$RQLITE_API_USER" -p "$RQLITE_API_PASS" -else - echo "Usage: $0 {cluster|api}" - exit 1 -fi -EOF - -sudo chown debros:debros "$DEBROS_DIR/bin/rqlite-connect" -sudo chmod 755 "$DEBROS_DIR/bin/rqlite-connect" - -echo "✅ Production security setup complete!" -echo "" -echo "📋 Security Summary:" -echo " - RQLite authentication enabled" -echo " - Firewall configured with IP restrictions" -echo " - Cluster credentials generated and stored" -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" -echo " - Auth: $KEYS_DIR/rqlite-cluster-auth" -echo "" -echo "🔌 Connect to RQLite:" -echo " - Cluster admin: $DEBROS_DIR/bin/rqlite-connect cluster" -echo " - API access: $DEBROS_DIR/bin/rqlite-connect api" -echo "" -echo "⚠️ IMPORTANT: Save these credentials securely!" -echo " Cluster User: $CLUSTER_USER" -echo " Cluster Pass: $CLUSTER_PASS"