mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-11 08:18:49 +00:00
feat: add production deployment documentation and service management commands
- Introduced a new section in the README for Production Deployment, detailing prerequisites, installation steps, and service management commands. - Added commands for starting, stopping, and restarting production services in the CLI, enhancing user control over service management. - Updated IPFS initialization to configure API, Gateway, and Swarm addresses to avoid port conflicts, improving deployment reliability. - Enhanced error handling and logging for service management operations, ensuring better feedback during execution.
This commit is contained in:
parent
52b3a99bb9
commit
b0ac58af3e
16
CHANGELOG.md
16
CHANGELOG.md
@ -13,6 +13,22 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant
|
||||
### Deprecated
|
||||
|
||||
### Fixed
|
||||
## [0.68.0] - 2025-11-11
|
||||
|
||||
### Added
|
||||
- Added comprehensive documentation for production deployment, including installation, upgrade, service management, and troubleshooting.
|
||||
- Added new CLI commands (`dbn prod start`, `dbn prod stop`, `dbn prod restart`) for convenient management of production systemd services.
|
||||
|
||||
### Changed
|
||||
- Updated IPFS configuration during production installation to use port 4501 for the API (to avoid conflicts with RQLite on port 5001) and port 8080 for the Gateway.
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- Ensured that IPFS configuration automatically disables AutoConf when a private swarm key is present during installation and upgrade, preventing startup errors.
|
||||
|
||||
## [0.67.7] - 2025-11-11
|
||||
|
||||
### 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.67.7
|
||||
VERSION := 0.68.0
|
||||
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)'
|
||||
|
||||
281
README.md
281
README.md
@ -6,6 +6,7 @@ DeBros Network is a decentralized peer-to-peer data platform built in Go. It com
|
||||
|
||||
- [At a Glance](#at-a-glance)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Production Deployment](#production-deployment)
|
||||
- [Components & Ports](#components--ports)
|
||||
- [Configuration Cheatsheet](#configuration-cheatsheet)
|
||||
- [CLI Highlights](#cli-highlights)
|
||||
@ -54,6 +55,286 @@ DeBros Network is a decentralized peer-to-peer data platform built in Go. It com
|
||||
./bin/dbn pubsub subscribe notifications 10s
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
DeBros Network can be deployed as production systemd services on Linux servers. The production installer handles all dependencies, configuration, and service management automatically.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **OS**: Ubuntu 20.04+, Debian 11+, or compatible Linux distribution
|
||||
- **Architecture**: `amd64` (x86_64) or `arm64` (aarch64)
|
||||
- **Permissions**: Root access (use `sudo`)
|
||||
- **Resources**: Minimum 2GB RAM, 10GB disk space, 2 CPU cores
|
||||
|
||||
### Installation
|
||||
|
||||
#### Quick Install
|
||||
|
||||
Install the CLI tool first:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://install.debros.network | sudo bash
|
||||
```
|
||||
|
||||
Or download manually from [GitHub Releases](https://github.com/DeBrosOfficial/network/releases).
|
||||
|
||||
#### Bootstrap Node (First Node)
|
||||
|
||||
Install the first node in your cluster:
|
||||
|
||||
```bash
|
||||
# Main branch (stable releases)
|
||||
sudo dbn prod install --bootstrap
|
||||
|
||||
# Nightly branch (latest development)
|
||||
sudo dbn prod install --bootstrap --branch nightly
|
||||
```
|
||||
|
||||
The bootstrap node initializes the cluster and serves as the primary peer for other nodes to join.
|
||||
|
||||
#### Secondary Node (Join Existing Cluster)
|
||||
|
||||
Join an existing cluster by providing the bootstrap node's IP and peer multiaddr:
|
||||
|
||||
```bash
|
||||
sudo dbn prod install \
|
||||
--vps-ip <your_public_ip> \
|
||||
--peers /ip4/<bootstrap_ip>/tcp/4001/p2p/<peer_id> \
|
||||
--branch nightly
|
||||
```
|
||||
|
||||
**Required flags for secondary nodes:**
|
||||
|
||||
- `--vps-ip`: Your server's public IP address
|
||||
- `--peers`: Comma-separated list of bootstrap peer multiaddrs
|
||||
|
||||
**Optional flags:**
|
||||
|
||||
- `--branch`: Git branch to use (`main` or `nightly`, default: `main`)
|
||||
- `--domain`: Domain name for HTTPS (enables ACME/Let's Encrypt)
|
||||
- `--bootstrap-join`: Raft join address for secondary bootstrap nodes
|
||||
|
||||
#### Secondary Bootstrap Node
|
||||
|
||||
Create a secondary bootstrap node that joins an existing Raft cluster:
|
||||
|
||||
```bash
|
||||
sudo dbn prod install \
|
||||
--bootstrap \
|
||||
--vps-ip <your_public_ip> \
|
||||
--bootstrap-join <primary_bootstrap_ip>:7001 \
|
||||
--branch nightly
|
||||
```
|
||||
|
||||
### Branch Selection
|
||||
|
||||
DeBros Network supports two branches:
|
||||
|
||||
- **`main`**: Stable releases (default). Recommended for production.
|
||||
- **`nightly`**: Latest development builds. Use for testing new features.
|
||||
|
||||
**Branch preference is saved automatically** during installation. Future upgrades will use the same branch unless you override it with `--branch`.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Install with nightly branch
|
||||
sudo dbn prod install --bootstrap --branch nightly
|
||||
|
||||
# Upgrade using saved branch preference
|
||||
sudo dbn prod upgrade --restart
|
||||
|
||||
# Upgrade and switch to main branch
|
||||
sudo dbn prod upgrade --restart --branch main
|
||||
```
|
||||
|
||||
### Upgrade
|
||||
|
||||
Upgrade an existing installation to the latest version:
|
||||
|
||||
```bash
|
||||
# Upgrade using saved branch preference
|
||||
sudo dbn prod upgrade --restart
|
||||
|
||||
# Upgrade and switch branches
|
||||
sudo dbn prod upgrade --restart --branch nightly
|
||||
|
||||
# Upgrade without restarting services
|
||||
sudo dbn prod upgrade
|
||||
```
|
||||
|
||||
The upgrade process:
|
||||
|
||||
1. ✅ Checks prerequisites
|
||||
2. ✅ Updates binaries (fetches latest from selected branch)
|
||||
3. ✅ Preserves existing configurations and data
|
||||
4. ✅ Updates configurations to latest format
|
||||
5. ✅ Updates systemd service files
|
||||
6. ✅ Optionally restarts services (`--restart` flag)
|
||||
|
||||
**Note**: The upgrade automatically detects your node type (bootstrap vs. regular node) and preserves all secrets, data, and configurations.
|
||||
|
||||
### Service Management
|
||||
|
||||
All services run as systemd units under the `debros` user.
|
||||
|
||||
#### Check Status
|
||||
|
||||
```bash
|
||||
# View status of all services
|
||||
dbn prod status
|
||||
|
||||
# Or use systemctl directly
|
||||
systemctl status debros-node-bootstrap
|
||||
systemctl status debros-ipfs-bootstrap
|
||||
systemctl status debros-gateway
|
||||
```
|
||||
|
||||
#### View Logs
|
||||
|
||||
```bash
|
||||
# View recent logs
|
||||
dbn prod logs node
|
||||
|
||||
# Follow logs in real-time
|
||||
dbn prod logs node --follow
|
||||
|
||||
# View specific service logs
|
||||
dbn prod logs ipfs --follow
|
||||
dbn prod logs gateway --follow
|
||||
```
|
||||
|
||||
Available log targets: `node`, `ipfs`, `ipfs-cluster`, `rqlite`, `olric`, `gateway`
|
||||
|
||||
#### Service Control Commands
|
||||
|
||||
Use `dbn prod` commands for convenient service management:
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
sudo dbn prod start
|
||||
|
||||
# Stop all services
|
||||
sudo dbn prod stop
|
||||
|
||||
# Restart all services
|
||||
sudo dbn prod restart
|
||||
```
|
||||
|
||||
Or use `systemctl` directly for more control:
|
||||
|
||||
```bash
|
||||
# Restart all services
|
||||
sudo systemctl restart debros-*
|
||||
|
||||
# Restart specific service
|
||||
sudo systemctl restart debros-node-bootstrap
|
||||
|
||||
# Stop services
|
||||
sudo systemctl stop debros-*
|
||||
|
||||
# Start services
|
||||
sudo systemctl start debros-*
|
||||
|
||||
# Enable services (start on boot)
|
||||
sudo systemctl enable debros-*
|
||||
```
|
||||
|
||||
### Directory Structure
|
||||
|
||||
Production installations use `/home/debros/.debros/`:
|
||||
|
||||
```
|
||||
/home/debros/.debros/
|
||||
├── configs/ # Configuration files
|
||||
│ ├── bootstrap.yaml # Bootstrap node config
|
||||
│ ├── node.yaml # Regular node config
|
||||
│ ├── gateway.yaml # Gateway config
|
||||
│ └── olric/ # Olric cache config
|
||||
├── data/ # Runtime data
|
||||
│ ├── bootstrap/ # Bootstrap node data
|
||||
│ │ ├── ipfs/ # IPFS repository
|
||||
│ │ ├── ipfs-cluster/ # IPFS Cluster data
|
||||
│ │ └── rqlite/ # RQLite database
|
||||
│ └── node/ # Regular node data
|
||||
├── secrets/ # Secrets and keys
|
||||
│ ├── cluster-secret # IPFS Cluster secret
|
||||
│ └── swarm.key # IPFS swarm key
|
||||
├── logs/ # Service logs
|
||||
│ ├── node-bootstrap.log
|
||||
│ ├── ipfs-bootstrap.log
|
||||
│ └── gateway.log
|
||||
└── .branch # Saved branch preference
|
||||
```
|
||||
|
||||
### Uninstall
|
||||
|
||||
Remove all production services (preserves data and configs):
|
||||
|
||||
```bash
|
||||
sudo dbn prod uninstall
|
||||
```
|
||||
|
||||
This stops and removes all systemd services but keeps `/home/debros/.debros/` intact. To completely remove:
|
||||
|
||||
```bash
|
||||
sudo dbn prod uninstall
|
||||
sudo rm -rf /home/debros/.debros
|
||||
```
|
||||
|
||||
### Production Troubleshooting
|
||||
|
||||
#### Services Not Starting
|
||||
|
||||
```bash
|
||||
# Check service status
|
||||
systemctl status debros-node-bootstrap
|
||||
|
||||
# View detailed logs
|
||||
journalctl -u debros-node-bootstrap -n 100
|
||||
|
||||
# Check log files
|
||||
tail -f /home/debros/.debros/logs/node-bootstrap.log
|
||||
```
|
||||
|
||||
#### Configuration Issues
|
||||
|
||||
```bash
|
||||
# Verify configs exist
|
||||
ls -la /home/debros/.debros/configs/
|
||||
|
||||
# Regenerate configs (preserves secrets)
|
||||
sudo dbn prod upgrade --restart
|
||||
```
|
||||
|
||||
#### IPFS AutoConf Errors
|
||||
|
||||
If you see "AutoConf.Enabled=false but 'auto' placeholder is used" errors, the upgrade process should fix this automatically. If not:
|
||||
|
||||
```bash
|
||||
# Re-run upgrade to fix IPFS config
|
||||
sudo dbn prod upgrade --restart
|
||||
```
|
||||
|
||||
#### Port Conflicts
|
||||
|
||||
```bash
|
||||
# Check what's using ports
|
||||
sudo lsof -i :4001 # P2P port
|
||||
sudo lsof -i :5001 # RQLite HTTP
|
||||
sudo lsof -i :6001 # Gateway
|
||||
```
|
||||
|
||||
#### Reset Installation
|
||||
|
||||
To start fresh (⚠️ **destroys all data**):
|
||||
|
||||
```bash
|
||||
sudo dbn prod uninstall
|
||||
sudo rm -rf /home/debros/.debros
|
||||
sudo dbn prod install --bootstrap --branch nightly
|
||||
```
|
||||
|
||||
## Components & Ports
|
||||
|
||||
- **Bootstrap node**: P2P `4001`, RQLite HTTP `5001`, Raft `7001`
|
||||
|
||||
@ -28,6 +28,12 @@ func HandleProdCommand(args []string) {
|
||||
handleProdUpgrade(subargs)
|
||||
case "status":
|
||||
handleProdStatus()
|
||||
case "start":
|
||||
handleProdStart()
|
||||
case "stop":
|
||||
handleProdStop()
|
||||
case "restart":
|
||||
handleProdRestart()
|
||||
case "logs":
|
||||
handleProdLogs(subargs)
|
||||
case "uninstall":
|
||||
@ -59,6 +65,9 @@ func showProdHelp() {
|
||||
fmt.Printf(" --restart - Automatically restart services after upgrade\n")
|
||||
fmt.Printf(" --branch BRANCH - Git branch to use (main or nightly, uses saved preference if not specified)\n")
|
||||
fmt.Printf(" status - Show status of production services\n")
|
||||
fmt.Printf(" start - Start all production services (requires root/sudo)\n")
|
||||
fmt.Printf(" stop - Stop all production services (requires root/sudo)\n")
|
||||
fmt.Printf(" restart - Restart all production services (requires root/sudo)\n")
|
||||
fmt.Printf(" logs <service> - View production service logs\n")
|
||||
fmt.Printf(" Options:\n")
|
||||
fmt.Printf(" --follow - Follow logs in real-time\n")
|
||||
@ -76,6 +85,10 @@ func showProdHelp() {
|
||||
fmt.Printf(" sudo dbn prod upgrade --restart\n\n")
|
||||
fmt.Printf(" # Upgrade and switch to nightly branch\n")
|
||||
fmt.Printf(" sudo dbn prod upgrade --restart --branch nightly\n\n")
|
||||
fmt.Printf(" # Service management\n")
|
||||
fmt.Printf(" sudo dbn prod start\n")
|
||||
fmt.Printf(" sudo dbn prod stop\n")
|
||||
fmt.Printf(" sudo dbn prod restart\n\n")
|
||||
fmt.Printf(" dbn prod status\n")
|
||||
fmt.Printf(" dbn prod logs node --follow\n")
|
||||
}
|
||||
@ -452,6 +465,112 @@ func handleProdLogs(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// getProductionServices returns a list of all DeBros production service names that exist
|
||||
func getProductionServices() []string {
|
||||
// All possible service names (both bootstrap and node variants)
|
||||
allServices := []string{
|
||||
"debros-gateway",
|
||||
"debros-node-node",
|
||||
"debros-node-bootstrap",
|
||||
"debros-olric",
|
||||
"debros-rqlite-bootstrap",
|
||||
"debros-rqlite-node",
|
||||
"debros-ipfs-cluster-bootstrap",
|
||||
"debros-ipfs-cluster-node",
|
||||
"debros-ipfs-bootstrap",
|
||||
"debros-ipfs-node",
|
||||
}
|
||||
|
||||
// Filter to only existing services by checking if unit file exists
|
||||
var existing []string
|
||||
for _, svc := range allServices {
|
||||
unitPath := filepath.Join("/etc/systemd/system", svc+".service")
|
||||
if _, err := os.Stat(unitPath); err == nil {
|
||||
existing = append(existing, svc)
|
||||
}
|
||||
}
|
||||
|
||||
return existing
|
||||
}
|
||||
|
||||
func handleProdStart() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Fprintf(os.Stderr, "❌ Production commands must be run as root (use sudo)\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Starting all DeBros production services...\n")
|
||||
|
||||
services := getProductionServices()
|
||||
if len(services) == 0 {
|
||||
fmt.Printf(" ⚠️ No DeBros services found\n")
|
||||
return
|
||||
}
|
||||
|
||||
for _, svc := range services {
|
||||
cmd := exec.Command("systemctl", "start", svc)
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf(" ⚠️ Failed to start %s: %v\n", svc, err)
|
||||
} else {
|
||||
fmt.Printf(" ✓ Started %s\n", svc)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n✅ All services started\n")
|
||||
}
|
||||
|
||||
func handleProdStop() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Fprintf(os.Stderr, "❌ Production commands must be run as root (use sudo)\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Stopping all DeBros production services...\n")
|
||||
|
||||
services := getProductionServices()
|
||||
if len(services) == 0 {
|
||||
fmt.Printf(" ⚠️ No DeBros services found\n")
|
||||
return
|
||||
}
|
||||
|
||||
for _, svc := range services {
|
||||
cmd := exec.Command("systemctl", "stop", svc)
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf(" ⚠️ Failed to stop %s: %v\n", svc, err)
|
||||
} else {
|
||||
fmt.Printf(" ✓ Stopped %s\n", svc)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n✅ All services stopped\n")
|
||||
}
|
||||
|
||||
func handleProdRestart() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Fprintf(os.Stderr, "❌ Production commands must be run as root (use sudo)\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Restarting all DeBros production services...\n")
|
||||
|
||||
services := getProductionServices()
|
||||
if len(services) == 0 {
|
||||
fmt.Printf(" ⚠️ No DeBros services found\n")
|
||||
return
|
||||
}
|
||||
|
||||
for _, svc := range services {
|
||||
cmd := exec.Command("systemctl", "restart", svc)
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf(" ⚠️ Failed to restart %s: %v\n", svc, err)
|
||||
} else {
|
||||
fmt.Printf(" ✓ Restarted %s\n", svc)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n✅ All services restarted\n")
|
||||
}
|
||||
|
||||
func handleProdUninstall() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Fprintf(os.Stderr, "❌ Production uninstall must be run as root (use sudo)\n")
|
||||
|
||||
@ -355,7 +355,7 @@ func (bi *BinaryInstaller) InstallSystemDependencies() error {
|
||||
}
|
||||
|
||||
// InitializeIPFSRepo initializes an IPFS repository for a node
|
||||
func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swarmKeyPath string) error {
|
||||
func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swarmKeyPath string, apiPort, gatewayPort, swarmPort int) error {
|
||||
configPath := filepath.Join(ipfsRepoPath, "config")
|
||||
repoExists := false
|
||||
if _, err := os.Stat(configPath); err == nil {
|
||||
@ -393,6 +393,13 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
||||
swarmKeyExists = true
|
||||
}
|
||||
|
||||
// Configure IPFS addresses (API, Gateway, Swarm) by modifying the config file directly
|
||||
// This ensures the ports are set correctly and avoids conflicts with RQLite on port 5001
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Configuring IPFS addresses (API: %d, Gateway: %d, Swarm: %d)...\n", apiPort, gatewayPort, swarmPort)
|
||||
if err := bi.configureIPFSAddresses(ipfsRepoPath, apiPort, gatewayPort, swarmPort); err != nil {
|
||||
return fmt.Errorf("failed to configure IPFS addresses: %w", err)
|
||||
}
|
||||
|
||||
// Always disable AutoConf for private swarm when swarm.key is present
|
||||
// This is critical - IPFS will fail to start if AutoConf is enabled on a private network
|
||||
// We do this even for existing repos to fix repos initialized before this fix was applied
|
||||
@ -437,6 +444,44 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
||||
return nil
|
||||
}
|
||||
|
||||
// configureIPFSAddresses configures the IPFS API, Gateway, and Swarm addresses in the config file
|
||||
func (bi *BinaryInstaller) configureIPFSAddresses(ipfsRepoPath string, apiPort, gatewayPort, swarmPort int) error {
|
||||
configPath := filepath.Join(ipfsRepoPath, "config")
|
||||
|
||||
// Read existing config
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read IPFS config: %w", err)
|
||||
}
|
||||
|
||||
var config map[string]interface{}
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return fmt.Errorf("failed to parse IPFS config: %w", err)
|
||||
}
|
||||
|
||||
// Set Addresses
|
||||
config["Addresses"] = map[string]interface{}{
|
||||
"API": []string{fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", apiPort)},
|
||||
"Gateway": []string{fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", gatewayPort)},
|
||||
"Swarm": []string{
|
||||
fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", swarmPort),
|
||||
fmt.Sprintf("/ip6/::/tcp/%d", swarmPort),
|
||||
},
|
||||
}
|
||||
|
||||
// Write config back
|
||||
updatedData, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal IPFS config: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(configPath, updatedData, 0600); err != nil {
|
||||
return fmt.Errorf("failed to write IPFS config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitializeIPFSClusterConfig initializes IPFS Cluster configuration
|
||||
// This runs `ipfs-cluster-service init` to create the service.json configuration file.
|
||||
// For existing installations, it ensures the cluster secret is up to date.
|
||||
|
||||
@ -263,8 +263,9 @@ func (ps *ProductionSetup) Phase2cInitializeServices(nodeType string) error {
|
||||
dataDir := filepath.Join(ps.debrosDir, "data", nodeType)
|
||||
|
||||
// Initialize IPFS repo with correct path structure
|
||||
// Use port 4501 for API (to avoid conflict with RQLite on 5001), 8080 for gateway (standard), 4001 for swarm
|
||||
ipfsRepoPath := filepath.Join(dataDir, "ipfs", "repo")
|
||||
if err := ps.binaryInstaller.InitializeIPFSRepo(nodeType, ipfsRepoPath, filepath.Join(ps.debrosDir, "secrets", "swarm.key")); err != nil {
|
||||
if err := ps.binaryInstaller.InitializeIPFSRepo(nodeType, ipfsRepoPath, filepath.Join(ps.debrosDir, "secrets", "swarm.key"), 4501, 8080, 4001); err != nil {
|
||||
return fmt.Errorf("failed to initialize IPFS repo: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user