Skip to content

Commit c035f10

Browse files
committed
fix: explicitly peer private-mode IPFS nodes after startup
mDNS auto-discovery has proven unreliable across different Docker networking environments - verified working on Docker Desktop but not on a native Linux Docker bridge network (e.g. GitHub Actions runners), where sibling IPFS nodes never connected to each other despite the earlier AutoConf/Bootstrap fix, causing shared storage downloads to hang/time out again. Query each member's real PeerID via its own IPFS API after containers start, then call swarm/peering/add on every other member so they connect to (and persistently reconnect to) each other, regardless of whether mDNS works in a given environment. Signed-off-by: Enrique Lacal <enrique.lacal@kaleido.io>
1 parent 12206e5 commit c035f10

2 files changed

Lines changed: 45 additions & 111 deletions

File tree

.github/workflows/debug-ipfs-mdns.yml

Lines changed: 0 additions & 111 deletions
This file was deleted.

internal/stacks/stack_manager.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"net"
24+
"net/http"
2425
"os"
2526
"os/exec"
2627
"path"
@@ -588,6 +589,46 @@ func (s *StackManager) copyIPFSInitScriptToVolumes() error {
588589
return nil
589590
}
590591

592+
// peerIPFSNodes explicitly peers every private-mode IPFS node with every
593+
// other member's node. mDNS auto-discovery has proven unreliable across
594+
// different Docker networking environments (it connected nodes on Docker
595+
// Desktop but not on a native Linux Docker bridge network, such as GitHub
596+
// Actions runners use), so without this, members' IPFS nodes may never
597+
// connect to each other and shared storage downloads will hang/time out.
598+
func (s *StackManager) peerIPFSNodes() error {
599+
if !s.Stack.IPFSMode.Equals(types.IPFSModePrivate) || len(s.Stack.Members) < 2 {
600+
return nil
601+
}
602+
603+
type ipfsIDResponse struct {
604+
ID string `json:"ID"`
605+
}
606+
607+
peerIDs := make(map[string]string, len(s.Stack.Members))
608+
for _, member := range s.Stack.Members {
609+
var idResp ipfsIDResponse
610+
url := fmt.Sprintf("http://127.0.0.1:%d/api/v0/id", member.ExposedIPFSApiPort)
611+
if err := core.RequestWithRetry(s.ctx, http.MethodPost, url, nil, &idResp); err != nil {
612+
return fmt.Errorf("failed to get IPFS peer ID for member %s: %w", member.ID, err)
613+
}
614+
peerIDs[member.ID] = idResp.ID
615+
}
616+
617+
for _, member := range s.Stack.Members {
618+
for _, other := range s.Stack.Members {
619+
if member.ID == other.ID {
620+
continue
621+
}
622+
addr := fmt.Sprintf("/dns4/ipfs_%s/tcp/4001/p2p/%s", other.ID, peerIDs[other.ID])
623+
url := fmt.Sprintf("http://127.0.0.1:%d/api/v0/swarm/peering/add?arg=%s", member.ExposedIPFSApiPort, addr)
624+
if err := core.RequestWithRetry(s.ctx, http.MethodPost, url, nil, nil); err != nil {
625+
return fmt.Errorf("failed to peer IPFS node %s with %s: %w", member.ID, other.ID, err)
626+
}
627+
}
628+
}
629+
return nil
630+
}
631+
591632
func (s *StackManager) createMember(id string, index int, options *types.InitOptions, external bool) (*types.Organization, error) {
592633
serviceBase := options.ServicesBasePort + (index * 100)
593634
ptmBase := options.PtmBasePort + (index * 10)
@@ -945,6 +986,10 @@ func (s *StackManager) runFirstTimeSetup(options *types.StartOptions) (messages
945986
return messages, err
946987
}
947988

989+
if err := s.peerIPFSNodes(); err != nil {
990+
return messages, err
991+
}
992+
948993
for i, tp := range s.tokenProviders {
949994
if !s.Stack.DisableTokenFactories {
950995
result, err := tp.DeploySmartContracts(i)

0 commit comments

Comments
 (0)