Dynamic Configuration
for IPFS Mainnet
Updateable system registry for routing systems, bootstrap peers, special TLD resolvers, and delegated endpoints.
Overview
IPFS Mainnet AutoConf provides a standardized, extensible configuration format for IPFS implementations to discover and configure routing systems, bootstrap peers, DNS resolvers for special TLDs, and delegated endpoints dynamically.
What is AutoConf?
This version introduces a system-centric approach that moves away from hardcoded profiles to a flexible registry where routing systems declare their capabilities and endpoints specify which systems they support. This enables:
- Dynamic System Discovery: New routing systems can be added without breaking existing clients
- Future-Proof API Versioning: Endpoints can support multiple API versions simultaneously
- Clear Separation: Native configuration (bootstrap peers) vs delegated configuration (HTTP endpoints)
- Client Choice: Implementations decide whether to use native or delegated routing per system
- API Compatibility: Clients ignore unknown APIs and use only the endpoints they understand
Key Principles
- Extensibility: Unknown APIs are safely ignored, allowing gradual ecosystem evolution
- Endpoint-Level Capabilities: Each endpoint declares exactly which APIs it supports
- Configurable Caching: Clients cache configurations locally, for the shorter of
AutoConfTTLand their own refresh interval
Configuration Format
The AutoConf format consists of the following sections that work together to provide comprehensive routing configuration:
AutoConfVersion
Purpose: Timestamp-based version identifier (YYYYMMDDNN format), similar to DNS SOA sequence numbers
Usage: Identifies a published revision, so operators and logs can name the exact configuration a node is running. Clients detect changes via HTTP ETag and Last-Modified rather than by comparing this number.
Example: 2025072801 (July 28, 2025, version 01)
AutoConfSchema
Purpose: Schema version number for breaking changes
Usage: Allows clients to handle different config formats
Current: 1
AutoConfTTL
Purpose: Cache duration in seconds
Usage: A hint for how long clients should cache the config. Clients use the shorter of this value and their own configured refresh interval, so this can bring a refresh forward but never push it back.
Default: 86400 (24 hours)
SystemRegistry
Purpose: Discovery registry of all routing systems
Contains: Link to documentation, native configuration, and delegated API capabilities
Usage: Clients check here to understand system capabilities
Note: InfoURL and Description are for people reading this document. Clients do not consume them.
DNSResolvers
Purpose: DNS-over-HTTPS resolvers for special TLDs
Usage: Resolving non-ICANN domains like .eth
Format: Maps eTLD to array of DoH endpoints
Note: Implementations use default resolver from the OS or explicitly choose DoH resolver (e.g. in browsers)
DelegatedEndpoints
Purpose: HTTP endpoints that provide routing services via delegation
Contains: Endpoint URL, supported systems, Read/Write API paths
Usage: Clients use these when they don't have native system support
Well Known Routing Systems
The registry defines routing systems with their capabilities and access methods:
System Routing Types
IPFS routing systems can operate in different modes depending on client capabilities and requirements:
Examples: DHT participation, local DNS resolver
Best for: Full nodes, daemons with persistent connectivity
Used when native support is unavailable or impractical
Best for: Browsers, mobile apps, resource-constrained environments
Clients choose based on their capabilities and constraints
Best for: Flexible implementations that adapt to environment
Implementation Decision Flow
| System | Type | Purpose | APIs |
|---|---|---|---|
| AminoDHT | 🔀 Native + Delegated | P2P content and peer routing via Kademlia DHT | /routing/v1/{providers,peers,ipns} (R/W for ipns) |
| IPNI | 🌐 Delegated Only | Fast content discovery from large storage providers | /routing/v1/providers |
| Example | 🌐 Delegated Only | Test system for verifying graceful handling of unknown APIs | /example/v0/{read,write} |
Adding New Systems
The schema supports gradual ecosystem evolution: add systems to the registry with their API paths, update endpoints to declare support, and existing clients will ignore unknown APIs while new clients can leverage them immediately.
This extensibility mechanism allows IPFS Mainnet to introduce new routing systems by providing delegated HTTP adapters that existing software can understand and query. For example, a novel routing system can be deployed with HTTP endpoints that speak the standard routing protocols, enabling immediate adoption without requiring native implementation support from existing IPFS clients. This approach enables:
- Zero-friction deployment: New systems work immediately with all existing IPFS implementations that support delegated routing
- Gradual native adoption: Implementations can add native support over time while using delegation as a bridge
- Innovation without fragmentation: Experimental routing systems can be tested in production without breaking compatibility
- Backward compatibility: Older clients continue working, simply ignoring systems they don't recognize
Client Implementation
Clients should process the configuration by checking available systems, determining native vs delegated routing support, and configuring DNS resolvers for special TLDs.
API Versioning Strategy
Delegated utility servers can support multiple API versions simultaneously:
{
"DelegatedEndpoints": {
"https://future-endpoint.example": {
"Systems": ["AminoDHT", "NewSystem"],
"Read": [
"/routing/v1/providers", // Legacy API
"/routing/v2/providers", // Enhanced API
"/routing/v2/content" // New capability
],
"Write": [
"/routing/v1/ipns", // Legacy publishing
"/routing/v2/ipns" // Enhanced publishing
]
}
}
}
Implementations Status
The Go ecosystem fetches this document at runtime today. The JavaScript ecosystem reaches the same endpoints indirectly, by pinning equivalent values at build time rather than fetching them, so it does not pick up changes published here. Tracked in #3.
| Implementation | Status | Since | Notes |
|---|---|---|---|
| boxo/autoconf | ✅ Shipped | v0.42.1 | Reference client. The Go implementations below all use it. |
| Kubo | ✅ Shipped | v0.37.0 | Configured via AutoConf. |
| Rainbow | ✅ Shipped | v1.24.0 | Enabled by default via RAINBOW_AUTOCONF, --autoconf-url to override. |
| Someguy | ✅ Shipped | v0.16.0 | --autoconf / SOMEGUY_AUTOCONF. |
| Helia | ☑️ Indirect | v2.1.0 | Hardcodes both the bootstrap peer list and https://delegated-ipfs.dev as the default delegated router. |
| helia-verified-fetch | ☑️ Indirect | v1.0.0 | Falls back to https://delegated-ipfs.dev when no routers are supplied. Present since its first release. |
| Service Worker Gateway | ☑️ Indirect | v1.0.0 | Hardcodes https://delegated-ipfs.dev for both routing and DNS. Present since its first release. |
Processing Algorithm
// 1. Check SystemRegistry for available routing systems
for system in autoconf.SystemRegistry:
if client.supportsNative(system):
// Use native implementation with NativeConfig
client.configureNative(system, autoconf.SystemRegistry[system].NativeConfig)
else:
// Use delegated routing via HTTP endpoints
for endpoint in autoconf.DelegatedEndpoints:
if system in endpoint.Systems:
// Filter to only APIs this client recognizes
supportedReadAPIs = client.filterKnownAPIs(endpoint.Read)
supportedWriteAPIs = client.filterKnownAPIs(endpoint.Write)
// Configure delegated routing using only supported APIs
client.configureDelegated(system, endpoint, supportedReadAPIs, supportedWriteAPIs)
// 2. Configure DNS resolvers for special TLDs
// Note: Implementations use OS default or explicit DoH resolver
for etld, resolvers in autoconf.DNSResolvers:
client.configureDNS(etld, resolvers)
Example Implementation
async function configureIPFS() {
// Fetch AutoConf
const response = await fetch('https://conf.ipfs-mainnet.org/autoconf.json');
const autoconf = await response.json();
// Cache for the shorter of our own interval and AutoConfTTL from the config
const maxCacheSeconds = 24 * 60 * 60; // 24 hours
const cacheTTL = Math.min(maxCacheSeconds, autoconf.AutoConfTTL || maxCacheSeconds);
localStorage.setItem('ipfs-autoconf', JSON.stringify({
data: autoconf,
expires: Date.now() + (cacheTTL * 1000)
}));
// Define which systems this client supports natively
const nativeSystems = ['AminoDHT']; // This client has native DHT support
// Configure routing systems
for (const [systemName, systemConfig] of Object.entries(autoconf.SystemRegistry)) {
if (nativeSystems.includes(systemName)) {
// Use native implementation
if (systemName === 'AminoDHT' && canRunDHT()) {
configureNativeDHT(systemConfig.NativeConfig.Bootstrap);
}
} else {
// Delegate to HTTP endpoints for unsupported systems
for (const [url, endpoint] of Object.entries(autoconf.DelegatedEndpoints)) {
if (endpoint.Systems.includes(systemName)) {
configureDelegatedRouting(systemName, url, endpoint);
}
}
}
}
// Configure DNS resolvers for special TLDs
// Note: Use OS default resolver or explicit DoH for general domains
for (const [etld, resolvers] of Object.entries(autoconf.DNSResolvers)) {
configureDNSResolver(etld, resolvers);
}
}
Failure Behavior
Losing this server must never take a node off the network. Here is how the reference implementation, boxo/autoconf v0.42.1, does it.
Configuration comes from three sources. Any failure falls through to the next:
- The network. Validated before it is used or stored.
- The cached copy, at any age. Log how old it is and carry on.
- Defaults built into the client. What a node with no cache uses.
Every failure behaves the same. DNS failure, refused connection, timeout, 404, 500, an HTML error page, malformed JSON, an oversized body: all mean no usable response, all fall through.
Validate before caching. A broken or hostile response then cannot poison the copy a node falls back on.
Reference limits, sane defaults rather than requirements: 2 MiB response cap, 5 second timeout, 24 hour refresh. Within that interval the cached copy is used without contacting the server, and ETag and Last-Modified make an unchanged document cost a 304 and no body.
Implementation Guidance
Different IPFS implementations have different constraints and capabilities. Here are recommendations for common deployment scenarios:
🌐 Browser Implementations
Constraints: Limited networking, no raw sockets, CORS restrictions
Recommendations:
- Prefer delegated routing for all systems
- Use HTTPS endpoints exclusively
- Implement aggressive caching
- Consider service worker integration
// Browser-optimized configuration
const browserDefaults = {
preferDelegated: ['AminoDHT', 'IPNI'],
enableNative: [] // No native routing in browsers
};
🖥️ Daemon Implementations
Capabilities: Full networking, persistent storage, background processing
Recommendations:
- Prefer native DHT participation
- Use delegated routing for specialized systems (IPNI)
- Enable both TCP and QUIC transports
- Participate in content providing (native AminoDHT only)
// Daemon-optimized configuration
const daemonDefaults = {
preferNative: ['AminoDHT'],
preferDelegated: ['IPNI'],
enableProviding: true // Only works with native AminoDHT
};
📱 Mobile/Resource-Constrained
Constraints: Battery life, bandwidth limits, intermittent connectivity
Recommendations:
- Hybrid approach based on network type
- Delegated routing on cellular
- Optional native DHT on WiFi
- Aggressive connection pruning
// Mobile-optimized configuration
const mobileDefaults = {
preferDelegated: ['AminoDHT', 'IPNI'],
enableNativeOnWifi: ['AminoDHT'],
maxConnections: 50
};
Platform-Specific Considerations
Implementers should make these decisions at build time based on their target platform rather than reading them from the autoconf. The autoconf provides the what (available systems and endpoints), while your implementation decides the how (native vs delegated routing).
// Instead of reading profiles from autoconf, hard-code platform decisions:
function getRoutingStrategy() {
if (typeof window !== 'undefined' && !window.require) {
// Browser environment
return { preferDelegated: true };
} else if (process.env.IPFS_LITE_MODE) {
// Resource-constrained environment
return { preferDelegated: true, maxConnections: 50 };
} else {
// Full daemon environment
return { preferNative: true, enableProviding: true }; // Providing requires native AminoDHT
}
}
This approach provides clearer separation between configuration data (what services are available) and implementation decisions (how to use those services), making both the autoconf and implementations simpler and more maintainable.
Security Considerations
Fetching defaults over the network adds a party you have to trust. This section covers how changes to this document are controlled, and what to do if depending on it at runtime is not acceptable for your deployment.
Publishing controls
This document is published from a public repository, so every revision and its author are on the record and any change can be diffed against what came before. Proposed changes are checked in CI with the same client that nodes run: a document that carries no bootstrap peers, or that does not advance AutoConfVersion, fails that check.
If you need stronger guarantees
For deployments where losing control of routing is unacceptable, do not depend on this service at runtime:
- Turn it off and supply your own values. In Kubo,
ipfs config profile apply autoconf-offsetsAutoConf.Enabledto false and emptiesBootstrap,DNS.Resolvers,Routing.DelegatedRoutersandIpns.DelegatedPublishers. It empties those fields rather than filling them in, so you must populate the ones you need before the node is useful. - Serve your own copy. Point
AutoConf.URLat a document you host and update on your own schedule, after reviewing what changed here. - Keep a floor. Whatever you do, retain a set of bootstrap peers and endpoints that works without this service, so an outage or a bad publish cannot leave your nodes with nowhere to connect. A client can also build this floor for itself:
boxo/bootstrapperiodically saves a sample of currently connected peers as temporary bootstrappers, so a node that has been online before does not depend on the published list alone.