Skip to content

Commit

Permalink
refactor: ForgeClient → AutoTLS
Browse files Browse the repository at this point in the history
addressing UX/DX feedback from Daniel, switching to self-explanatory
configuration section
  • Loading branch information
lidel committed Oct 28, 2024
1 parent 7eeda1b commit 99b7757
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 46 deletions.
18 changes: 9 additions & 9 deletions config/forge.go → config/autotls.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@ package config

import p2pforge "github.com/ipshipyard/p2p-forge/client"

// ForgeClient includes optional configuration of p2p-forge client of service
// AutoTLS includes optional configuration of p2p-forge client of service
// for obtaining a domain and TLS certificate to improve connectivity for web
// browser clients. More: https://github.com/ipshipyard/p2p-forge#readme
type ForgeClient struct {
type AutoTLS struct {
// Enables the p2p-forge feature
Enabled Flag `json:",omitempty"`

// Optional override of the parent domain that will be used
ForgeDomain *OptionalString `json:",omitempty"`
DomainSuffix *OptionalString `json:",omitempty"`

// Optional override of HTTP API that acts as ACME DNS-01 Challenge broker
ForgeEndpoint *OptionalString `json:",omitempty"`
RegistrationEndpoint *OptionalString `json:",omitempty"`

// Optional Authorization token, used with private/test instances of p2p-forge
ForgeAuth *OptionalString `json:",omitempty"`
RegistrationToken *OptionalString `json:",omitempty"`

// Optional override of CA ACME API used by p2p-forge system
CAEndpoint *OptionalString `json:",omitempty"`
}

const (
DefaultForgeEnabled = false // experimental, opt-in for now (https://github.com/ipfs/kubo/pull/10521)
DefaultForgeDomain = p2pforge.DefaultForgeDomain
DefaultForgeEndpoint = p2pforge.DefaultForgeEndpoint
DefaultCAEndpoint = p2pforge.DefaultCAEndpoint
DefaultAutoTLSEnabled = false // experimental, opt-in for now (https://github.com/ipfs/kubo/pull/10521)
DefaultDomainSuffix = p2pforge.DefaultForgeDomain
DefaultRegistrationEndpoint = p2pforge.DefaultForgeEndpoint
DefaultCAEndpoint = p2pforge.DefaultCAEndpoint
)
7 changes: 4 additions & 3 deletions config/swarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ type SwarmConfig struct {
// ResourceMgr configures the libp2p Network Resource Manager
ResourceMgr ResourceMgr

// ForgeClient controls the client of a service for obtaining a domain
// and TLS certificate to improve connectivity for web browser clients.
ForgeClient ForgeClient
// AutoTLS controls the client of a service for obtaining and configuring a
// domain and TLS certificate to improve connectivity for web browser
// clients.
AutoTLS AutoTLS
}

type RelayClient struct {
Expand Down
10 changes: 5 additions & 5 deletions core/node/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
enableRelayTransport := cfg.Swarm.Transports.Network.Relay.WithDefault(true) // nolint
enableRelayService := cfg.Swarm.RelayService.Enabled.WithDefault(enableRelayTransport)
enableRelayClient := cfg.Swarm.RelayClient.Enabled.WithDefault(enableRelayTransport)
enableForgeClient := cfg.Swarm.ForgeClient.Enabled.WithDefault(config.DefaultForgeEnabled)
enableAutoTLS := cfg.Swarm.AutoTLS.Enabled.WithDefault(config.DefaultAutoTLSEnabled)

// Log error when relay subsystem could not be initialized due to missing dependency
if !enableRelayTransport {
Expand All @@ -124,8 +124,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
logger.Fatal("Failed to enable `Swarm.RelayClient`, it requires `Swarm.Transports.Network.Relay` to be true.")
}
}
if enableForgeClient && !cfg.Swarm.Transports.Network.Websocket.WithDefault(true) {
logger.Fatal("Failed to enable `Swarm.ForgeClient`, it requires `Swarm.Transports.Network.Websocket` to be true.")
if enableAutoTLS && !cfg.Swarm.Transports.Network.Websocket.WithDefault(true) {
logger.Fatal("Failed to enable `Swarm.AutoTLS`, it requires `Swarm.Transports.Network.Websocket` to be true.")
}

// Gather all the options
Expand All @@ -137,8 +137,8 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part

// Services (resource management)
fx.Provide(libp2p.ResourceManager(bcfg.Repo.Path(), cfg.Swarm, userResourceOverrides)),
maybeProvide(libp2p.P2PForgeCertMgr(cfg.Swarm.ForgeClient), enableForgeClient),
maybeInvoke(libp2p.StartP2PForgeClient, enableForgeClient),
maybeProvide(libp2p.P2PForgeCertMgr(cfg.Swarm.AutoTLS), enableAutoTLS),
maybeInvoke(libp2p.StartP2PAutoTLS, enableAutoTLS),
fx.Provide(libp2p.AddrFilters(cfg.Swarm.AddrFilters)),
fx.Provide(libp2p.AddrsFactory(cfg.Addresses.Announce, cfg.Addresses.AppendAnnounce, cfg.Addresses.NoAnnounce)),
fx.Provide(libp2p.SmuxTransport(cfg.Swarm.Transports)),
Expand Down
10 changes: 5 additions & 5 deletions core/node/libp2p/addrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func ListenOn(addresses []string) interface{} {
}
}

func P2PForgeCertMgr(cfg config.ForgeClient) interface{} {
func P2PForgeCertMgr(cfg config.AutoTLS) interface{} {
return func() (*p2pforge.P2PForgeCertMgr, error) {
storagePath, err := config.Path("", "p2p-forge-certs")
if err != nil {
Expand All @@ -149,10 +149,10 @@ func P2PForgeCertMgr(cfg config.ForgeClient) interface{} {

certMgr, err := p2pforge.NewP2PForgeCertMgr(
p2pforge.WithLogger(forgeLogger.Sugar()),
p2pforge.WithForgeDomain(cfg.ForgeDomain.WithDefault(config.DefaultForgeDomain)),
p2pforge.WithForgeRegistrationEndpoint(cfg.ForgeEndpoint.WithDefault(config.DefaultForgeEndpoint)),
p2pforge.WithForgeDomain(cfg.DomainSuffix.WithDefault(config.DefaultDomainSuffix)),
p2pforge.WithForgeRegistrationEndpoint(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)),
p2pforge.WithCAEndpoint(cfg.CAEndpoint.WithDefault(config.DefaultCAEndpoint)),
p2pforge.WithForgeAuth(cfg.ForgeAuth.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))),
p2pforge.WithForgeAuth(cfg.RegistrationToken.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))),
p2pforge.WithUserAgent(version.GetUserAgentVersion()),
p2pforge.WithCertificateStorage(&certmagic.FileStorage{Path: storagePath}))
if err != nil {
Expand All @@ -163,7 +163,7 @@ func P2PForgeCertMgr(cfg config.ForgeClient) interface{} {
}
}

func StartP2PForgeClient(lc fx.Lifecycle, certMgr *p2pforge.P2PForgeCertMgr, h host.Host) {
func StartP2PAutoTLS(lc fx.Lifecycle, certMgr *p2pforge.P2PForgeCertMgr, h host.Host) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
certMgr.ProvideHost(h)
Expand Down
2 changes: 1 addition & 1 deletion docs/changelogs/v0.32.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
This release introduces an experimental feature that significantly improves how browsers can connect to Kubo node.
Opt-in configuration allows Kubo node to obtain trusted certificates for Secure WebSocket (WSS) connections without manual intervention.

See [`Swarm.ForgeClient`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmforgeclient) for details how to enable it. We appreciate you testing and providing an early feedback.
See [`Swarm.AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#swarmforgeclient) for details how to enable it. We appreciate you testing and providing an early feedback.

#### go-libp2p updates

Expand Down
47 changes: 24 additions & 23 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ config file at runtime.
- [`Swarm.DisableBandwidthMetrics`](#swarmdisablebandwidthmetrics)
- [`Swarm.DisableNatPortMap`](#swarmdisablenatportmap)
- [`Swarm.EnableHolePunching`](#swarmenableholepunching)
- [`Swarm.ForgeClient`](#swarmforgeclient)
- [`Swarm.ForgeClient.Enabled`](#swarmforgeclientenabled)
- [`Swarm.ForgeClient.ForgeDomain`](#swarmforgeclientforgedomain)
- [`Swarm.ForgeClient.ForgeEndpoint`](#swarmforgeclientforgeendpoint)
- [`Swarm.ForgeClient.ForgeAuth`](#swarmforgeclientforgeauth)
- [`Swarm.ForgeClient.CAEndpoint`](#swarmforgeclientcaendpoint)
- [`Swarm.AutoTLS`](#swarmautotls)
- [`Swarm.AutoTLS.Enabled`](#swarmautotlsenabled)
- [`Swarm.AutoTLS.DomainSuffix`](#swarmautotlsdomainsuffix)
- [`Swarm.AutoTLS.RegistrationEndpoint`](#swarmautotlsregistrationendpoint)
- [`Swarm.AutoTLS.RegistrationToken`](#swarmautotlsregistrationtoken)
- [`Swarm.AutoTLS.CAEndpoint`](#swarmautotlscaendpoint)
- [`Swarm.EnableAutoRelay`](#swarmenableautorelay)
- [`Swarm.RelayClient`](#swarmrelayclient)
- [`Swarm.RelayClient.Enabled`](#swarmrelayclientenabled)
Expand Down Expand Up @@ -1722,19 +1722,20 @@ Default: `true`

Type: `flag`

### `Swarm.ForgeClient`
### `Swarm.AutoTLS`

AutoTLS enables publicly reachable Kubo nodes, i.e. nodes dialable from the public internet, to get a wildcard TLS certificate unique to their PeerID at `*.[PeerID].libp2p.direct` without needing to register and configure a domain name. This enables direct libp2p connections and direct retrieval of IPFS content from browsers using Secure WebSockets.
AutoTLS enables publicly reachable Kubo nodes (those dialable from the public
internet) to automatically obtain a wildcard TLS certificate for a DNS name
unique to their PeerID at `*.[PeerID].libp2p.direct`. This enables direct
libp2p connections and retrieval of IPFS content from browsers using Secure
WebSockets, without requiring manual domain registration and configuration.

Under the hood, the `libp2p.direct` acts as a an [ACME DNS-01 Challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) broker for getting wildcard TLS certificate for `*.[PeerID].libp2p.direct`.
Under the hood, `libp2p.direct` acts as an [ACME DNS-01 Challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)
broker for obtaining these wildcard TLS certificates.

By default, AutoTLS requests TLS certificates from Let's Encrypt and uses a `libp2p.direct` subdomain.
By default, the certificates are requested from Let's Encrypt.
Origin and rationale for this project can be found in [community.letsencrypt.org discussion].

In short, [p2p-forge] provides a publicly diallable Kubo with a domain name for their PeerID (`peerid.libp2p.direct`),
and acts as [ACME DNS-01 Challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)
broker to allow Kubo to get a wildcard TLS cert for that domain (`*.peerid.libp2p.direct`).

> [!NOTE]
> Public good infrastructure at `libp2p.direct` is run by the team at [Interplanetary Shipyard](https://ipshipyard.com).
>
Expand All @@ -1747,16 +1748,16 @@ Default: `{}`

Type: `object`

#### `Swarm.ForgeClient.Enabled`
#### `Swarm.AutoTLS.Enabled`

> [!CAUTION]
> This is an EXPERIMENTAL feature and should not be used in production yet.
> Feel free to enable it and report issues if you want to help with testing.
> Feel free to enable it and [report issues](https://github.com/ipfs/kubo/issues/new/choose) if you want to help with testing.
Enables **EXPERIMENTAL** [p2p-forge] client. This feature works only if your Kubo node is publicly diallable.

If enabled, it will detect when `.../tls/sni/.../ws` is present in [`Addresses.Swarm`](#addressesswarm)
and SNI is matching `Swarm.ForgeClient.ForgeDomain`, and set up a trusted TLS certificate matching the domain name used in Secure WebSockets (WSS) listener.
and SNI is matching `Swarm.AutoTLS.DomainSuffix`, and set up a trusted TLS certificate matching the domain name used in Secure WebSockets (WSS) listener.

If you want to test this, add `/ip4/0.0.0.0/tcp/4082/tls/sni/*.libp2p.direct/ws` to [`Addresses.Swarm`](#addressesswarm).

Expand All @@ -1766,16 +1767,16 @@ Default: `false`

Type: `flag`

#### `Swarm.ForgeClient.ForgeDomain`
#### `Swarm.AutoTLS.DomainSuffix`

Optional override of the parent domain that will be used in DNS+TLS+WebSockets multiaddrs generated by [p2p-forge] client.
Optional override of the parent domain suffix that will be used in DNS+TLS+WebSockets multiaddrs generated by [p2p-forge] client.
Do not change this unless you self-host [p2p-forge].

Default: `libp2p.direct` (public good run by [Interplanetary Shipyard](https://ipshipyard.com))

Type: `optionalString`

#### `Swarm.ForgeClient.ForgeEndpoint`
#### `Swarm.AutoTLS.RegistrationEndpoint`

Optional override of [p2p-forge] HTTP registration API.
Do not change this unless you self-host [p2p-forge].
Expand All @@ -1784,16 +1785,16 @@ Default: `https://registration.libp2p.direct` (public good run by [Interplanetar

Type: `optionalString`

#### `Swarm.ForgeClient.ForgeAuth`
#### `Swarm.AutoTLS.RegistrationToken`

Optional value for `Forge-Authorization` token sent with request to `ForgeEndpoint`
Optional value for `Forge-Authorization` token sent with request to `RegistrationEndpoint`
(useful for private/self-hosted/test instances of [p2p-forge]).

Default: `""`

Type: `optionalString`

#### `Swarm.ForgeClient.CAEndpoint`
#### `Swarm.AutoTLS.CAEndpoint`

Optional override of CA ACME API used by [p2p-forge] system.

Expand Down

0 comments on commit 99b7757

Please sign in to comment.