mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-12 23:18:49 +00:00
feat: enhance configuration handling for IPFS and cluster initialization
- Updated `select_data_dir_check` to handle both absolute and relative config paths, improving flexibility in configuration file management. - Enhanced `DefaultPath` to check for config files in both legacy and production directories, ensuring backward compatibility. - Modified `InitializeIPFSClusterConfig` to include cluster secret management and improve error handling during initialization. - Added functionality to update the cluster secret in the service.json configuration file, enhancing security and configurability.
This commit is contained in:
parent
6ba0a824e0
commit
a33d03c6b2
16
CHANGELOG.md
16
CHANGELOG.md
@ -13,6 +13,22 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant
|
|||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
## [0.67.4] - 2025-11-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
\n
|
||||||
|
### Changed
|
||||||
|
- Improved configuration file loading logic to support absolute paths for config files.
|
||||||
|
- Updated IPFS Cluster initialization during setup to run `ipfs-cluster-service init` and automatically configure the cluster secret.
|
||||||
|
- IPFS repositories initialized with a private swarm key will now automatically disable AutoConf.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed configuration path resolution to correctly check for config files in both the legacy (`~/.debros/`) and production (`~/.debros/configs/`) directories.
|
||||||
|
|
||||||
## [0.67.3] - 2025-11-11
|
## [0.67.3] - 2025-11-11
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ test-e2e:
|
|||||||
|
|
||||||
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports install-hooks kill
|
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports install-hooks kill
|
||||||
|
|
||||||
VERSION := 0.67.3
|
VERSION := 0.67.4
|
||||||
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||||
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)'
|
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)'
|
||||||
|
|||||||
@ -66,23 +66,32 @@ func check_if_should_open_help(help *bool) {
|
|||||||
func select_data_dir_check(configName *string) {
|
func select_data_dir_check(configName *string) {
|
||||||
logger := setup_logger(logging.ComponentNode)
|
logger := setup_logger(logging.ComponentNode)
|
||||||
|
|
||||||
// Ensure config directory exists and is writable
|
var configPath string
|
||||||
_, err := config.EnsureConfigDir()
|
var err error
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to ensure config directory", zap.Error(err))
|
|
||||||
fmt.Fprintf(os.Stderr, "\n❌ Configuration Error:\n")
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to create/access config directory: %v\n", err)
|
|
||||||
fmt.Fprintf(os.Stderr, "\nPlease ensure:\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " 1. Home directory is accessible: %s\n", os.ExpandEnv("~"))
|
|
||||||
fmt.Fprintf(os.Stderr, " 2. You have write permissions to home directory\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " 3. Disk space is available\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
configPath, err := config.DefaultPath(*configName)
|
// Check if configName is an absolute path
|
||||||
if err != nil {
|
if filepath.IsAbs(*configName) {
|
||||||
logger.Error("Failed to determine config path", zap.Error(err))
|
// Use absolute path directly
|
||||||
os.Exit(1)
|
configPath = *configName
|
||||||
|
} else {
|
||||||
|
// Ensure config directory exists and is writable
|
||||||
|
_, err = config.EnsureConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to ensure config directory", zap.Error(err))
|
||||||
|
fmt.Fprintf(os.Stderr, "\n❌ Configuration Error:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Failed to create/access config directory: %v\n", err)
|
||||||
|
fmt.Fprintf(os.Stderr, "\nPlease ensure:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " 1. Home directory is accessible: %s\n", os.ExpandEnv("~"))
|
||||||
|
fmt.Fprintf(os.Stderr, " 2. You have write permissions to home directory\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " 3. Disk space is available\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
configPath, err = config.DefaultPath(*configName)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to determine config path", zap.Error(err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(configPath); err != nil {
|
if _, err := os.Stat(configPath); err != nil {
|
||||||
@ -232,15 +241,21 @@ func main() {
|
|||||||
|
|
||||||
check_if_should_open_help(help)
|
check_if_should_open_help(help)
|
||||||
|
|
||||||
// Check if config file exists
|
// Check if config file exists and determine path
|
||||||
select_data_dir_check(configName)
|
select_data_dir_check(configName)
|
||||||
|
|
||||||
// Load configuration from ~/.debros/node.yaml
|
// Determine config path (handle both absolute and relative paths)
|
||||||
configPath, err := config.DefaultPath(*configName)
|
var configPath string
|
||||||
if err != nil {
|
var err error
|
||||||
logger.Error("Failed to determine config path", zap.Error(err))
|
if filepath.IsAbs(*configName) {
|
||||||
fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err)
|
configPath = *configName
|
||||||
os.Exit(1)
|
} else {
|
||||||
|
configPath, err = config.DefaultPath(*configName)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to determine config path", zap.Error(err))
|
||||||
|
fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg *config.Config
|
var cfg *config.Config
|
||||||
|
|||||||
@ -29,10 +29,26 @@ func EnsureConfigDir() (string, error) {
|
|||||||
|
|
||||||
// DefaultPath returns the path to the config file for the given component name.
|
// DefaultPath returns the path to the config file for the given component name.
|
||||||
// component should be e.g., "node.yaml", "bootstrap.yaml", "gateway.yaml"
|
// component should be e.g., "node.yaml", "bootstrap.yaml", "gateway.yaml"
|
||||||
|
// It checks both ~/.debros/ and ~/.debros/configs/ for backward compatibility.
|
||||||
func DefaultPath(component string) (string, error) {
|
func DefaultPath(component string) (string, error) {
|
||||||
dir, err := ConfigDir()
|
dir, err := ConfigDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return filepath.Join(dir, component), nil
|
|
||||||
|
// First check in ~/.debros/configs/ (production installer location)
|
||||||
|
configsPath := filepath.Join(dir, "configs", component)
|
||||||
|
if _, err := os.Stat(configsPath); err == nil {
|
||||||
|
return configsPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to ~/.debros/ (legacy/development location)
|
||||||
|
legacyPath := filepath.Join(dir, component)
|
||||||
|
if _, err := os.Stat(legacyPath); err == nil {
|
||||||
|
return legacyPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return configs path as default (even if it doesn't exist yet)
|
||||||
|
// This allows the error message to show the expected production location
|
||||||
|
return configsPath, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package production
|
package production
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -363,10 +364,22 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy swarm key if present
|
// Copy swarm key if present
|
||||||
|
swarmKeyExists := false
|
||||||
if data, err := os.ReadFile(swarmKeyPath); err == nil {
|
if data, err := os.ReadFile(swarmKeyPath); err == nil {
|
||||||
if err := os.WriteFile(filepath.Join(ipfsRepoPath, "swarm.key"), data, 0600); err != nil {
|
if err := os.WriteFile(filepath.Join(ipfsRepoPath, "swarm.key"), data, 0600); err != nil {
|
||||||
return fmt.Errorf("failed to copy swarm key: %w", err)
|
return fmt.Errorf("failed to copy swarm key: %w", err)
|
||||||
}
|
}
|
||||||
|
swarmKeyExists = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable AutoConf for private swarm (required when swarm.key is present)
|
||||||
|
// This prevents IPFS from trying to use the public mainnet AutoConf service
|
||||||
|
if swarmKeyExists {
|
||||||
|
cmd = exec.Command(ipfsBinary, "config", "--json", "AutoConf.Enabled", "false")
|
||||||
|
cmd.Env = append(os.Environ(), "IPFS_PATH="+ipfsRepoPath)
|
||||||
|
if output, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("failed to disable AutoConf: %v\n%s", err, string(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix ownership
|
// Fix ownership
|
||||||
@ -376,8 +389,7 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InitializeIPFSClusterConfig initializes IPFS Cluster configuration
|
// InitializeIPFSClusterConfig initializes IPFS Cluster configuration
|
||||||
// Note: This is a placeholder config. The full initialization will occur via `ipfs-cluster-service init`
|
// This runs `ipfs-cluster-service init` to create the service.json configuration file.
|
||||||
// which is run during Phase2cInitializeServices with the IPFS_CLUSTER_PATH env var set.
|
|
||||||
func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret string, ipfsAPIPort int) error {
|
func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret string, ipfsAPIPort int) error {
|
||||||
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
||||||
if _, err := os.Stat(serviceJSONPath); err == nil {
|
if _, err := os.Stat(serviceJSONPath); err == nil {
|
||||||
@ -391,7 +403,72 @@ func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, cl
|
|||||||
return fmt.Errorf("failed to create IPFS Cluster directory: %w", err)
|
return fmt.Errorf("failed to create IPFS Cluster directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix ownership before running init
|
||||||
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
||||||
|
|
||||||
|
// Resolve ipfs-cluster-service binary path
|
||||||
|
clusterBinary, err := bi.ResolveBinaryPath("ipfs-cluster-service", "/usr/local/bin/ipfs-cluster-service", "/usr/bin/ipfs-cluster-service")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ipfs-cluster-service binary not found: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize cluster config with ipfs-cluster-service init
|
||||||
|
// This creates the service.json file with all required sections
|
||||||
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Initializing IPFS Cluster config...\n")
|
||||||
|
cmd := exec.Command(clusterBinary, "init", "--force")
|
||||||
|
cmd.Env = append(os.Environ(), "IPFS_CLUSTER_PATH="+clusterPath)
|
||||||
|
if output, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("failed to initialize IPFS Cluster config: %v\n%s", err, string(output))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the cluster secret in service.json if provided
|
||||||
|
if clusterSecret != "" {
|
||||||
|
if err := bi.updateClusterSecret(clusterPath, clusterSecret); err != nil {
|
||||||
|
return fmt.Errorf("failed to update cluster secret: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix ownership again after init
|
||||||
|
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateClusterSecret updates the secret field in IPFS Cluster service.json
|
||||||
|
func (bi *BinaryInstaller) updateClusterSecret(clusterPath, secret string) error {
|
||||||
|
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
||||||
|
|
||||||
|
// Read existing config
|
||||||
|
data, err := os.ReadFile(serviceJSONPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read service.json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse JSON
|
||||||
|
var config map[string]interface{}
|
||||||
|
if err := json.Unmarshal(data, &config); err != nil {
|
||||||
|
return fmt.Errorf("failed to parse service.json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cluster secret
|
||||||
|
if cluster, ok := config["cluster"].(map[string]interface{}); ok {
|
||||||
|
cluster["secret"] = secret
|
||||||
|
} else {
|
||||||
|
config["cluster"] = map[string]interface{}{
|
||||||
|
"secret": secret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write back
|
||||||
|
updatedData, err := json.MarshalIndent(config, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal service.json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(serviceJSONPath, updatedData, 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to write service.json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -231,10 +231,14 @@ func (ps *ProductionSetup) Phase2cInitializeServices(nodeType string) error {
|
|||||||
return fmt.Errorf("failed to initialize IPFS repo: %w", err)
|
return fmt.Errorf("failed to initialize IPFS repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize IPFS Cluster path (just ensure directory exists, actual init happens in daemon startup)
|
// Initialize IPFS Cluster config (runs ipfs-cluster-service init)
|
||||||
clusterPath := filepath.Join(dataDir, "ipfs-cluster")
|
clusterPath := filepath.Join(dataDir, "ipfs-cluster")
|
||||||
if err := ps.binaryInstaller.InitializeIPFSClusterConfig(nodeType, clusterPath, "", 4501); err != nil {
|
clusterSecret, err := ps.secretGenerator.EnsureClusterSecret()
|
||||||
ps.logf(" ⚠️ IPFS Cluster initialization warning: %v", err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get cluster secret: %w", err)
|
||||||
|
}
|
||||||
|
if err := ps.binaryInstaller.InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret, 4501); err != nil {
|
||||||
|
return fmt.Errorf("failed to initialize IPFS Cluster: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize RQLite data directory
|
// Initialize RQLite data directory
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user