Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
4bf7f27
feat: prototype autoclient library
lidel Jul 18, 2025
a72b8e1
feat(config): prototype autoconfig profile
lidel Jul 18, 2025
120bb82
feat: prototype embedded repo migrations
lidel Jul 18, 2025
51a49f9
feat: prototype of `ipfs config` support for `auto`
lidel Jul 24, 2025
a860748
docs: MustGetConfigWithMainnetFallbacks
lidel Jul 24, 2025
302dcdf
chore: lint + cleanup redundant tests
lidel Jul 24, 2025
d23374c
refactor: use const with profile names
lidel Jul 24, 2025
355bc3d
refactor: cfg.BootstrapPeers returns raw Bootstrap
lidel Jul 24, 2025
626a99f
fix: use resolved versions for making decisions
lidel Jul 24, 2025
1d91f11
refactor: Β Bootstrap[Peers]WithAutoConfig
lidel Jul 24, 2025
f629d8b
fix(cli): bootstrap cmd with auto
lidel Jul 24, 2025
0e75e4f
refactor: cleanup
lidel Jul 25, 2025
e711c3c
test: multiple consecutive --expand-auto calls
lidel Jul 25, 2025
d18a1fe
refactor: dry and useful logs
lidel Jul 25, 2025
7088d88
refactor: autoconfig .last-refresh
lidel Jul 25, 2025
e1e4e23
fix: `ipfs bootstrap add auto`
lidel Jul 26, 2025
53a642c
docs: AutoConfig in changelog
lidel Jul 26, 2025
273e18e
chore: update func name
lidel Jul 26, 2025
24d552d
refactor: schema v4
lidel Jul 30, 2025
e2476e9
test: DNSResolver validation
lidel Jul 30, 2025
e9f8ce9
docs: autoconfig changelog
lidel Jul 30, 2025
3d34f41
test: basic ipns publishing work in ci (offline)
lidel Jul 30, 2025
e4eb581
chore: cleanup to use testdata
lidel Jul 30, 2025
2a196dc
test(coreapi): ipns name
lidel Jul 30, 2025
a68d581
fix(docker): copy boxo/autoconfig
lidel Jul 30, 2025
8fa6527
fix(autoconfig): real ipni fallback
lidel Jul 30, 2025
a57df38
fix: restore legacy defaultRepo
lidel Jul 31, 2025
9480b93
test: restore coreiface from master
lidel Jul 31, 2025
85e80d4
chore: restore previous namesys wiring
lidel Jul 31, 2025
7585807
refactor: simplify constructDefaultHTTPRouters
lidel Jul 31, 2025
b3975a2
refactor: cleanup config/autoconfig.go
lidel Jul 31, 2025
00c9d9c
fix: thread-safe cache
lidel Jul 31, 2025
82f2b59
refactor: MustGetConfig fallback handling
lidel Aug 1, 2025
2e22eba
test: ParseAndValidateRoutingURL
lidel Aug 1, 2025
24e6aa4
fix: simpler cache dir
lidel Aug 1, 2025
cf8b596
refactor(config): remove need for passing repoPath
lidel Aug 1, 2025
374ba05
chore: collapse diffs of generated data
lidel Aug 1, 2025
1df21cd
chore: restore master code
lidel Aug 1, 2025
f7c2112
test: error cases for autoconfig.json fetch
lidel Aug 1, 2025
f5fe36f
chore: placeholder
lidel Aug 1, 2025
e52befe
refactor: clenup startAutoConfigUpdater
lidel Aug 1, 2025
03a2a3c
test(autoconfig): ipfs swarm connect
lidel Aug 1, 2025
146ef49
refactor: better names for Must* funcs
lidel Aug 1, 2025
3e4a854
fix(fx): ClearCachedNode
lidel Aug 1, 2025
ef98774
test: TestHTTPCachingBehavior and cleanup
lidel Aug 1, 2025
1a7230c
test: TestAutoConfigIPNS
lidel Aug 1, 2025
814723e
test(autoconfig) Routing.Type=auto|delegated
lidel Aug 2, 2025
36acffe
fix: go vet
lidel Aug 2, 2025
332ab2f
test: migration and autoconfig sharness
lidel Aug 3, 2025
a5f6777
fix: sync.RWMutex
lidel Aug 3, 2025
70dbdc8
test(cli): migration_legacy_15_to_17_test.go
lidel Aug 4, 2025
44dec15
test: testCLIUsesCacheOnlyDaemonUpdatesBackground
lidel Aug 4, 2025
e77f434
fix: t0066-migration.sh
lidel Aug 4, 2025
a6efc94
refactor: autoconfig β†’ autoconf
lidel Aug 4, 2025
35e521d
fix: validate AutoConfSchema 1
lidel Aug 4, 2025
1a73236
docs: highlights and deprecations
lidel Aug 4, 2025
7f3bcea
test: testAutoConfWithHTTPS
lidel Aug 4, 2025
5a6c5ab
docs: boxo/autoconf
lidel Aug 4, 2025
491b1c3
docs: examples in boxo/autoconf/README.md
lidel Aug 5, 2025
c71e9d8
Merge branch 'master' into feat-mainnet-autoconfig
gammazero Aug 11, 2025
6a32e60
remove unused import
gammazero Aug 11, 2025
ea6c3e4
Merge branch 'master' into feat-mainnet-autoconfig
gammazero Aug 11, 2025
285be62
Merge branch 'master' into feat-mainnet-autoconfig
gammazero Aug 11, 2025
13357e3
chore: config β†’ conf
lidel Aug 12, 2025
8fd1829
refactor: boxo/autoconf extraction prep
lidel Aug 13, 2025
ebb948f
refactor: boxo/autoconf cleanup, part 1
lidel Aug 13, 2025
95065fd
Merge branch 'master' into feat-mainnet-autoconfig
lidel Aug 13, 2025
564382f
tests: switch to testify
lidel Aug 13, 2025
d88c0d0
fix: log warn when no cache available
lidel Aug 13, 2025
c2129d7
refactor: improve lock scopes
lidel Aug 13, 2025
a4e0671
chore: move atomicfile
lidel Aug 13, 2025
cfa0bcc
refactor: simplify the path operations
lidel Aug 13, 2025
70860e0
refactor: code simplifications
lidel Aug 13, 2025
0a9a5b7
refactor: reuse buildEndpointURL
lidel Aug 13, 2025
a0bac20
fix: Errorf
lidel Aug 13, 2025
c890bfd
chore: remove FromCache
lidel Aug 13, 2025
c0269f4
fix: panic on nil client
lidel Aug 13, 2025
3a6ec69
chore: preallocate slice
lidel Aug 13, 2025
62f67d6
refactor: slices.Contains
lidel Aug 13, 2025
af51a49
refactor: review feedback cleanup
lidel Aug 13, 2025
54df810
refactor: core/node/libp2p/host.go
lidel Aug 13, 2025
b0cdf44
refactor: move autoclient to boxo#997
lidel Aug 13, 2025
1946d45
fix: restore dockerfile
lidel Aug 13, 2025
5d4275e
chore: gofmt
lidel Aug 13, 2025
66fe0a8
Merge branch 'master' into feat-mainnet-autoconfig
gammazero Aug 14, 2025
2176ae4
merge: origin/master into feat-mainnet-autoconfig
lidel Aug 15, 2025
7f027e4
docs: concise changelog
lidel Aug 15, 2025
9321e46
chore: update to latest boxo#997
lidel Aug 15, 2025
018b73b
chore: update to boxo@main
lidel Aug 15, 2025
e4e08a3
merge: origin/master into feat-mainnet-autoconfig
lidel Aug 18, 2025
f2ca7d9
fix: telemetry bootstrap check for autoconf
lidel Aug 18, 2025
f3b8ed3
feat: autoconf telemetry
lidel Aug 18, 2025
2bb5276
test: telemetry schema regression guard
lidel Aug 18, 2025
f0314d0
test: use atomic.Int32 for cleaner counter handling
lidel Aug 18, 2025
0eb4a02
test: remove emojis from test logs
lidel Aug 18, 2025
dc41fbb
test: clarify bootstrap peer round-trip test
lidel Aug 18, 2025
9ffbf88
test: simplify IPNS error tests
lidel Aug 18, 2025
a7b0b21
refactor: rename --delegated-only to --allow-delegated
lidel Aug 19, 2025
470d4db
refactor: make AutoConf.URL implicit like AutoTLS
lidel Aug 19, 2025
0da54e0
fix: sort profile names in config help output
lidel Aug 19, 2025
8ec830b
test: AutoConf in bootstrap add default test
lidel Aug 19, 2025
ccd2388
fix: allow ipfs repo migrate to run without daemon
lidel Aug 19, 2025
6e75456
refactor: make Migration config optional
lidel Aug 19, 2025
d028a23
Merge branch 'master' into feat-mainnet-autoconfig
lidel Aug 19, 2025
2b32db3
fix(migration): use implicit defaults for AutoConf fields
lidel Aug 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: prototype embedded repo migrations
this needs more testing and work, but we will do that
after autoconfig is wired in future commits
  • Loading branch information
lidel committed Jul 18, 2025
commit 120bb8294ef1c610fdff8b8167255f0e39af6f9f
117 changes: 65 additions & 52 deletions cmd/ipfs/kubo/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
}

var cacheMigrations, pinMigrations bool
var fetcher migrations.Fetcher
var externalMigrationFetcher migrations.Fetcher

// acquire the repo lock _before_ constructing a node. we need to make
// sure we are permitted to access the resources (datastore, etc.)
Expand All @@ -294,65 +294,78 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
}

if !domigrate {
fmt.Println("Not running migrations of fs-repo now.")
fmt.Println("Please get fs-repo-migrations from https://dist.ipfs.tech")
fmt.Println("Not running migrations of fs-repo now. Re-run daemon with --migrate or see 'ipfs repo migrate --help'")
return errors.New("fs-repo requires migration")
}

// Read Migration section of IPFS config
configFileOpt, _ := req.Options[commands.ConfigFileOption].(string)
migrationCfg, err := migrations.ReadMigrationConfig(cctx.ConfigRoot, configFileOpt)
// Try embedded migrations first
err = migrations.RunEmbeddedMigrations(cctx.Context(), fsrepo.RepoVersion, cctx.ConfigRoot, false)
if err != nil {
return err
}

// Define function to create IPFS fetcher. Do not supply an
// already-constructed IPFS fetcher, because this may be expensive and
// not needed according to migration config. Instead, supply a function
// to construct the particular IPFS fetcher implementation used here,
// which is called only if an IPFS fetcher is needed.
newIpfsFetcher := func(distPath string) migrations.Fetcher {
return ipfsfetcher.NewIpfsFetcher(distPath, 0, &cctx.ConfigRoot, configFileOpt)
}
fmt.Println("Embedded Kubo migrations failed, falling back to external binary migrations:")
fmt.Printf(" %s\n", err)

// Fetch migrations from current distribution, or location from environ
fetchDistPath := migrations.GetDistPathEnv(migrations.CurrentIpfsDist)
// Read Migration section of IPFS config for external migration fallback
// Note: External migrations only apply to repo versions <17. From repo version 17+,
// all migrations are embedded in Kubo and don't require external binaries.
configFileOpt, _ := req.Options[commands.ConfigFileOption].(string)
migrationCfg, err := migrations.ReadMigrationConfig(cctx.ConfigRoot, configFileOpt)
if err != nil {
return err
}

// Create fetchers according to migrationCfg.DownloadSources
fetcher, err = migrations.GetMigrationFetcher(migrationCfg.DownloadSources, fetchDistPath, newIpfsFetcher)
if err != nil {
return err
}
defer fetcher.Close()
// Define function to create IPFS fetcher. Do not supply an
// already-constructed IPFS fetcher, because this may be expensive and
// not needed according to migration config. Instead, supply a function
// to construct the particular IPFS fetcher implementation used here,
// which is called only if an IPFS fetcher is needed.
newIpfsFetcher := func(distPath string) migrations.Fetcher {
return ipfsfetcher.NewIpfsFetcher(distPath, 0, &cctx.ConfigRoot, configFileOpt)
}

if migrationCfg.Keep == "cache" {
cacheMigrations = true
} else if migrationCfg.Keep == "pin" {
pinMigrations = true
}
// Fetch migrations from current distribution, or location from environ
fetchDistPath := migrations.GetDistPathEnv(migrations.CurrentIpfsDist)

if cacheMigrations || pinMigrations {
// Create temp directory to store downloaded migration archives
migrations.DownloadDirectory, err = os.MkdirTemp("", "migrations")
// Create fetchers according to migrationCfg.DownloadSources
fetcher, err := migrations.GetMigrationFetcher(migrationCfg.DownloadSources, fetchDistPath, newIpfsFetcher)
if err != nil {
return err
}
// Defer cleanup of download directory so that it gets cleaned up
// if daemon returns early due to error
defer func() {
if migrations.DownloadDirectory != "" {
os.RemoveAll(migrations.DownloadDirectory)
defer fetcher.Close()

if migrationCfg.Keep == "cache" {
cacheMigrations = true
} else if migrationCfg.Keep == "pin" {
pinMigrations = true
}

if cacheMigrations || pinMigrations {
// Create temp directory to store downloaded migration archives
migrations.DownloadDirectory, err = os.MkdirTemp("", "migrations")
if err != nil {
return err
}
}()
}
// Defer cleanup of download directory so that it gets cleaned up
// if daemon returns early due to error
defer func() {
if migrations.DownloadDirectory != "" {
os.RemoveAll(migrations.DownloadDirectory)
}
}()
}

err = migrations.RunMigration(cctx.Context(), fetcher, fsrepo.RepoVersion, "", false)
if err != nil {
fmt.Println("The migrations of fs-repo failed:")
fmt.Printf(" %s\n", err)
fmt.Println("If you think this is a bug, please file an issue and include this whole log output.")
fmt.Println(" https://github.com/ipfs/fs-repo-migrations")
return err
// Fall back to external migration system
err = migrations.RunMigration(cctx.Context(), fetcher, fsrepo.RepoVersion, "", false)
if err != nil {
fmt.Println("The legacy migrations of fs-repo failed:")
fmt.Printf(" %s\n", err)
fmt.Println("If you think this is a bug, please file an issue and include this whole log output.")
fmt.Println(" https://github.com/ipfs/kubo")
return err
}

// External migrations completed successfully.
// Store migration data for later processing after node is created.
externalMigrationFetcher = fetcher
}

repo, err = fsrepo.Open(cctx.ConfigRoot)
Expand Down Expand Up @@ -566,9 +579,9 @@ take effect.
return err
}

// Add any files downloaded by migration.
if cacheMigrations || pinMigrations {
err = addMigrations(cctx.Context(), node, fetcher, pinMigrations)
// Add any files downloaded by external migrations (embedded migrations don't download files)
if externalMigrationFetcher != nil && (cacheMigrations || pinMigrations) {
err = addMigrations(cctx.Context(), node, externalMigrationFetcher, pinMigrations)
if err != nil {
fmt.Fprintln(os.Stderr, "Could not add migration to IPFS:", err)
}
Expand All @@ -577,10 +590,10 @@ take effect.
os.RemoveAll(migrations.DownloadDirectory)
migrations.DownloadDirectory = ""
}
if fetcher != nil {
if externalMigrationFetcher != nil {
// If there is an error closing the IpfsFetcher, then print error, but
// do not fail because of it.
err = fetcher.Close()
err = externalMigrationFetcher.Close()
if err != nil {
log.Errorf("error closing IPFS fetcher: %s", err)
}
Expand Down
7 changes: 4 additions & 3 deletions config/autoconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ type AutoConfig struct {
// LastUpdate is the timestamp of when the autoconfig was last successfully updated
LastUpdate *time.Time `json:",omitempty"`

// LastVersion stores the ETag or Last-Modified value from the last successful fetch
// LastVersion stores a string representation of AutoConfigVersion from the autoconfig.json file (if present),
// or falls back to ETag or Last-Modified header value from the last successful fetch
LastVersion string `json:",omitempty"`

// Interval is how often to check for updates
// CheckInterval is how often to check for updates
// Default: 24h
Interval *OptionalDuration `json:",omitempty"`
CheckInterval *OptionalDuration `json:",omitempty"`

// TLSInsecureSkipVerify allows skipping TLS verification (for testing only)
// Default: false
Expand Down
6 changes: 3 additions & 3 deletions config/autoconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func TestAutoConfigDefaults(t *testing.T) {
t.Error("expected AutoConfig.Enabled to be true by default")
}

// Test default interval
if cfg.AutoConfig.Interval == nil {
// Test default check interval
if cfg.AutoConfig.CheckInterval == nil {
// This is expected - nil means use default
duration := (*OptionalDuration)(nil).WithDefault(DefaultAutoConfigInterval)
if duration != 24*time.Hour {
t.Errorf("expected default interval to be 24h, got %v", duration)
t.Errorf("expected default check interval to be 24h, got %v", duration)
}
}
}
Expand Down
29 changes: 0 additions & 29 deletions config/bootstrap_peers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,18 @@ package config

import (
"errors"
"fmt"

peer "github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
)

// DefaultBootstrapAddresses are the hardcoded bootstrap addresses
// for IPFS. they are nodes run by the IPFS team. docs on these later.
// As with all p2p networks, bootstrap is an important security concern.
//
// NOTE: This is here -- and not inside cmd/ipfs/init.go -- because of an
// import dependency issue. TODO: move this into a config/default/ package.
var DefaultBootstrapAddresses = []string{
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", // rust-libp2p-server
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
"/dnsaddr/va1.bootstrap.libp2p.io/p2p/12D3KooWKnDdG3iXw9eTFijk3EWSunZcFi54Zka4wmtqtt6rPxc8", // js-libp2p-amino-dht-bootstrapper
"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
"/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
}

// ErrInvalidPeerAddr signals an address is not a valid peer address.
var ErrInvalidPeerAddr = errors.New("invalid peer address")

func (c *Config) BootstrapPeers() ([]peer.AddrInfo, error) {
return ParseBootstrapPeers(c.Bootstrap)
}

// DefaultBootstrapPeers returns the (parsed) set of default bootstrap peers.
// if it fails, it returns a meaningful error for the user.
// This is here (and not inside cmd/ipfs/init) because of module dependency problems.
func DefaultBootstrapPeers() ([]peer.AddrInfo, error) {
ps, err := ParseBootstrapPeers(DefaultBootstrapAddresses)
if err != nil {
return nil, fmt.Errorf(`failed to parse hardcoded bootstrap peers: %w
This is a problem with the ipfs codebase. Please report it to the dev team`, err)
}
return ps, nil
}

func (c *Config) SetBootstrapPeers(bps []peer.AddrInfo) {
c.Bootstrap = BootstrapPeerStrings(bps)
}
Expand Down
9 changes: 5 additions & 4 deletions config/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,12 @@ Inverse profile of the test profile.`,
Transform: func(c *Config) error {
c.Addresses = addressesConfig()

bootstrapPeers, err := DefaultBootstrapPeers()
if err != nil {
return err
// Use AutoConfig system for bootstrap peers
c.Bootstrap = []string{"auto"}
c.AutoConfig.Enabled = True
if c.AutoConfig.URL == "" {
c.AutoConfig.URL = DefaultAutoConfigURL
}
c.Bootstrap = appendSingle(c.Bootstrap, BootstrapPeerStrings(bootstrapPeers))

c.Swarm.DisableNatPortMap = false
c.Discovery.MDNS.Enabled = true
Expand Down
26 changes: 9 additions & 17 deletions core/commands/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
},
}

const (
defaultOptionName = "default"
)

var bootstrapAddCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Add peers to the bootstrap list.",
Expand All @@ -57,24 +53,16 @@ in the bootstrap list).
cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
},

Options: []cmds.Option{
cmds.BoolOption(defaultOptionName, "Add default bootstrap nodes. (Deprecated, use 'default' subcommand instead)"),
},
Subcommands: map[string]*cmds.Command{
"default": bootstrapAddDefaultCmd,
"auto": bootstrapAddDefaultCmd, // Alias for "default"
},

Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
deflt, _ := req.Options[defaultOptionName].(bool)

inputPeers := config.DefaultBootstrapAddresses
if !deflt {
if err := req.ParseBodyArgs(); err != nil {
return err
}

inputPeers = req.Arguments
if err := req.ParseBodyArgs(); err != nil {
return err
}
inputPeers := req.Arguments

if len(inputPeers) == 0 {
return errors.New("no bootstrap peers to add")
Expand Down Expand Up @@ -133,7 +121,11 @@ in the bootstrap list).`,
return err
}

added, err := bootstrapAdd(r, cfg, config.DefaultBootstrapAddresses)
if !cfg.AutoConfig.Enabled.WithDefault(true) {
return errors.New("cannot add default bootstrap peers: AutoConfig is disabled. Enable AutoConfig or add specific peer addresses")
}

added, err := bootstrapAdd(r, cfg, []string{"auto"})
if err != nil {
return err
}
Expand Down
Loading