mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-11 08:18:49 +00:00
feat: add port checking and anyone-client installation to production setup
- Introduced a new `PortChecker` type to verify port availability, enhancing service management during startup. - Updated the `BinaryInstaller` to install the `anyone-client` npm package globally, ensuring its availability for SOCKS5 proxy functionality. - Enhanced the `ProductionSetup` to include checks for port usage before starting the `anyone-client` service, improving conflict resolution. - Added logging for the installation and service creation of `anyone-client`, providing clearer feedback during the setup process.
This commit is contained in:
parent
4c1f842939
commit
90a26295a4
17
CHANGELOG.md
17
CHANGELOG.md
@ -13,6 +13,23 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant
|
||||
### Deprecated
|
||||
|
||||
### Fixed
|
||||
## [0.69.18] - 2025-11-22
|
||||
|
||||
### Added
|
||||
- Integrated `anyone-client` (SOCKS5 proxy) installation and systemd service (`debros-anyone-client.service`).
|
||||
- Added port availability checking logic to prevent conflicts when starting services (e.g., `anyone-client` on port 9050).
|
||||
|
||||
### Changed
|
||||
- Updated system dependencies installation to include `nodejs` and `npm` required for `anyone-client`.
|
||||
- Modified Olric configuration generation to bind to the specific VPS IP if provided, otherwise defaults to 0.0.0.0.
|
||||
- Improved IPFS Cluster initialization by passing `CLUSTER_SECRET` directly as an environment variable.
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
\n
|
||||
## [0.69.17] - 2025-11-21
|
||||
|
||||
### 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
|
||||
|
||||
VERSION := 0.69.17
|
||||
VERSION := 0.69.18
|
||||
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)'
|
||||
|
||||
@ -74,6 +74,8 @@ Install the CLI tool first:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://install.debros.network | sudo bash
|
||||
|
||||
./install-debros-network.sh --prerelease --nightly
|
||||
```
|
||||
|
||||
Or download manually from [GitHub Releases](https://github.com/DeBrosOfficial/network/releases).
|
||||
|
||||
@ -2,6 +2,7 @@ package production
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -297,3 +298,35 @@ func (rc *ResourceChecker) CheckCPU() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PortChecker checks if ports are available or in use
|
||||
type PortChecker struct{}
|
||||
|
||||
// NewPortChecker creates a new port checker
|
||||
func NewPortChecker() *PortChecker {
|
||||
return &PortChecker{}
|
||||
}
|
||||
|
||||
// IsPortInUse checks if a specific port is already in use
|
||||
func (pc *PortChecker) IsPortInUse(port int) bool {
|
||||
addr := fmt.Sprintf("localhost:%d", port)
|
||||
conn, err := net.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
// Port is not in use
|
||||
return false
|
||||
}
|
||||
defer conn.Close()
|
||||
// Port is in use
|
||||
return true
|
||||
}
|
||||
|
||||
// IsPortInUseOnHost checks if a port is in use on a specific host
|
||||
func (pc *PortChecker) IsPortInUseOnHost(host string, port int) bool {
|
||||
addr := net.JoinHostPort(host, fmt.Sprintf("%d", port))
|
||||
conn, err := net.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer conn.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -391,8 +391,8 @@ func (bi *BinaryInstaller) InstallSystemDependencies() error {
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Warning: apt update failed\n")
|
||||
}
|
||||
|
||||
// Install dependencies
|
||||
cmd = exec.Command("apt-get", "install", "-y", "curl", "git", "make", "build-essential", "wget")
|
||||
// Install dependencies including Node.js for anyone-client
|
||||
cmd = exec.Command("apt-get", "install", "-y", "curl", "git", "make", "build-essential", "wget", "nodejs", "npm")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to install dependencies: %w", err)
|
||||
}
|
||||
@ -567,6 +567,10 @@ func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, cl
|
||||
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)
|
||||
// Pass CLUSTER_SECRET to init so it writes the correct secret to service.json directly
|
||||
if clusterSecret != "" {
|
||||
cmd.Env = append(cmd.Env, "CLUSTER_SECRET="+clusterSecret)
|
||||
}
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to initialize IPFS Cluster config: %v\n%s", err, string(output))
|
||||
}
|
||||
@ -689,3 +693,28 @@ func (bi *BinaryInstaller) InitializeRQLiteDataDir(nodeType, dataDir string) err
|
||||
exec.Command("chown", "-R", "debros:debros", dataDir).Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
// InstallAnyoneClient installs the anyone-client npm package globally
|
||||
func (bi *BinaryInstaller) InstallAnyoneClient() error {
|
||||
// Check if anyone-client is already available
|
||||
if _, err := exec.LookPath("anyone-client"); err == nil {
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ anyone-client already installed\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing anyone-client...\n")
|
||||
|
||||
// Install anyone-client globally via npm
|
||||
cmd := exec.Command("npm", "install", "-g", "anyone-client")
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to install anyone-client: %w\n%s", err, string(output))
|
||||
}
|
||||
|
||||
// Verify installation
|
||||
if _, err := exec.LookPath("anyone-client"); err != nil {
|
||||
return fmt.Errorf("anyone-client installation failed - not found in PATH")
|
||||
}
|
||||
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ anyone-client installed\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ type ProductionSetup struct {
|
||||
osDetector *OSDetector
|
||||
archDetector *ArchitectureDetector
|
||||
resourceChecker *ResourceChecker
|
||||
portChecker *PortChecker
|
||||
fsProvisioner *FilesystemProvisioner
|
||||
userProvisioner *UserProvisioner
|
||||
stateDetector *StateDetector
|
||||
@ -90,6 +91,7 @@ func NewProductionSetup(debrosHome string, logWriter io.Writer, forceReconfigure
|
||||
osDetector: &OSDetector{},
|
||||
archDetector: &ArchitectureDetector{},
|
||||
resourceChecker: NewResourceChecker(),
|
||||
portChecker: NewPortChecker(),
|
||||
fsProvisioner: NewFilesystemProvisioner(debrosHome),
|
||||
userProvisioner: NewUserProvisioner("debros", debrosHome, "/bin/bash"),
|
||||
stateDetector: NewStateDetector(debrosDir),
|
||||
@ -258,6 +260,11 @@ func (ps *ProductionSetup) Phase2bInstallBinaries() error {
|
||||
ps.logf(" ⚠️ Olric install warning: %v", err)
|
||||
}
|
||||
|
||||
// Install anyone-client for SOCKS5 proxy
|
||||
if err := ps.binaryInstaller.InstallAnyoneClient(); err != nil {
|
||||
ps.logf(" ⚠️ anyone-client install warning: %v", err)
|
||||
}
|
||||
|
||||
// Install DeBros binaries
|
||||
if err := ps.binaryInstaller.InstallDeBrosBinaries(ps.branch, ps.debrosHome, ps.skipRepoUpdate); err != nil {
|
||||
return fmt.Errorf("failed to install DeBros binaries: %w", err)
|
||||
@ -439,9 +446,13 @@ func (ps *ProductionSetup) Phase4GenerateConfigs(isBootstrap bool, bootstrapPeer
|
||||
}
|
||||
ps.logf(" ✓ Gateway config generated")
|
||||
|
||||
// Olric config - bind to 0.0.0.0 to listen on all interfaces
|
||||
// Olric config - bind to vpsIP if provided, otherwise all interfaces
|
||||
// Gateway will connect using the specific address from olricServers list above
|
||||
olricConfig, err := ps.configGenerator.GenerateOlricConfig("0.0.0.0", 3320, 3322)
|
||||
olricBindAddr := vpsIP
|
||||
if olricBindAddr == "" {
|
||||
olricBindAddr = "0.0.0.0"
|
||||
}
|
||||
olricConfig, err := ps.configGenerator.GenerateOlricConfig(olricBindAddr, 3320, 3322)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate olric config: %w", err)
|
||||
}
|
||||
@ -522,6 +533,13 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(nodeType string, vpsIP st
|
||||
}
|
||||
ps.logf(" ✓ Gateway service created")
|
||||
|
||||
// Anyone Client service (SOCKS5 proxy)
|
||||
anyoneUnit := ps.serviceGenerator.GenerateAnyoneClientService()
|
||||
if err := ps.serviceController.WriteServiceUnit("debros-anyone-client.service", anyoneUnit); err != nil {
|
||||
return fmt.Errorf("failed to write Anyone Client service: %w", err)
|
||||
}
|
||||
ps.logf(" ✓ Anyone Client service created")
|
||||
|
||||
// Reload systemd daemon
|
||||
if err := ps.serviceController.DaemonReload(); err != nil {
|
||||
return fmt.Errorf("failed to reload systemd: %w", err)
|
||||
@ -529,7 +547,7 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(nodeType string, vpsIP st
|
||||
ps.logf(" ✓ Systemd daemon reloaded")
|
||||
|
||||
// Enable services (RQLite is managed by node, not as separate service)
|
||||
services := []string{unitName, clusterUnitName, "debros-olric.service", nodeUnitName, "debros-gateway.service"}
|
||||
services := []string{unitName, clusterUnitName, "debros-olric.service", nodeUnitName, "debros-gateway.service", "debros-anyone-client.service"}
|
||||
for _, svc := range services {
|
||||
if err := ps.serviceController.EnableService(svc); err != nil {
|
||||
ps.logf(" ⚠️ Failed to enable %s: %v", svc, err)
|
||||
@ -541,8 +559,17 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(nodeType string, vpsIP st
|
||||
// Start services in dependency order
|
||||
ps.logf(" Starting services...")
|
||||
|
||||
// Start infrastructure first (IPFS, Olric) - RQLite is managed by node
|
||||
// Start infrastructure first (IPFS, Olric, Anyone Client) - RQLite is managed by node
|
||||
infraServices := []string{unitName, "debros-olric.service"}
|
||||
|
||||
// Check if port 9050 is already in use (e.g., another anyone-client or similar service)
|
||||
if ps.portChecker.IsPortInUse(9050) {
|
||||
ps.logf(" ℹ️ Port 9050 is already in use (anyone-client or similar service running)")
|
||||
ps.logf(" ℹ️ Skipping debros-anyone-client startup - using existing service")
|
||||
} else {
|
||||
infraServices = append(infraServices, "debros-anyone-client.service")
|
||||
}
|
||||
|
||||
for _, svc := range infraServices {
|
||||
if err := ps.serviceController.StartService(svc); err != nil {
|
||||
ps.logf(" ⚠️ Failed to start %s: %v", svc, err)
|
||||
@ -592,9 +619,11 @@ func (ps *ProductionSetup) LogSetupComplete(peerID string) {
|
||||
ps.logf(" %s/logs/olric.log", ps.debrosDir)
|
||||
ps.logf(" %s/logs/node-bootstrap.log", ps.debrosDir)
|
||||
ps.logf(" %s/logs/gateway.log", ps.debrosDir)
|
||||
ps.logf(" %s/logs/anyone-client.log", ps.debrosDir)
|
||||
ps.logf("\nStart All Services:")
|
||||
ps.logf(" systemctl start debros-ipfs-bootstrap debros-ipfs-cluster-bootstrap debros-olric debros-node-bootstrap debros-gateway")
|
||||
ps.logf(" systemctl start debros-ipfs-bootstrap debros-ipfs-cluster-bootstrap debros-olric debros-anyone-client debros-node-bootstrap debros-gateway")
|
||||
ps.logf("\nVerify Installation:")
|
||||
ps.logf(" curl http://localhost:6001/health")
|
||||
ps.logf(" curl http://localhost:5001/status\n")
|
||||
ps.logf(" curl http://localhost:5001/status")
|
||||
ps.logf(" # Anyone Client SOCKS5 proxy on localhost:9050\n")
|
||||
}
|
||||
|
||||
@ -266,6 +266,37 @@ WantedBy=multi-user.target
|
||||
`, nodeService, olricService, nodeService, olricService, ssg.debrosHome, ssg.debrosHome, ssg.debrosHome, ssg.debrosDir, logFile, logFile, ssg.debrosDir)
|
||||
}
|
||||
|
||||
// GenerateAnyoneClientService generates the Anyone Client SOCKS5 proxy systemd unit
|
||||
func (ssg *SystemdServiceGenerator) GenerateAnyoneClientService() string {
|
||||
logFile := filepath.Join(ssg.debrosDir, "logs", "anyone-client.log")
|
||||
|
||||
return fmt.Sprintf(`[Unit]
|
||||
Description=Anyone Client SOCKS5 Proxy
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=debros
|
||||
Group=debros
|
||||
Environment=HOME=%[1]s
|
||||
ExecStart=/usr/bin/env anyone-client
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=file:%[2]s
|
||||
StandardError=file:%[2]s
|
||||
SyslogIdentifier=anyone-client
|
||||
|
||||
NoNewPrivileges=yes
|
||||
PrivateTmp=yes
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=%[3]s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`, ssg.debrosHome, logFile, ssg.debrosDir)
|
||||
}
|
||||
|
||||
// SystemdController manages systemd service operations
|
||||
type SystemdController struct {
|
||||
systemdDir string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user