Skip to content

feat(config): add Local Gateway URL for reverse proxy and Docker#2486

Merged
lidel merged 6 commits into
ipfs:mainfrom
NiltonVolpato:fix/local-gateway-override
Jun 30, 2026
Merged

feat(config): add Local Gateway URL for reverse proxy and Docker#2486
lidel merged 6 commits into
ipfs:mainfrom
NiltonVolpato:fix/local-gateway-override

Conversation

@NiltonVolpato

@NiltonVolpato NiltonVolpato commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Problem

When running Kubo in Docker or behind a reverse proxy, the WebUI generates incorrect gateway URLs (e.g., http://127.0.0.1:8080) for:

  • File downloads
  • Preview links
  • IPLD Explore page

This happens because the WebUI reads the gateway address from Kubo's config, which typically contains Docker-internal addresses like /ip4/0.0.0.0/tcp/8080 that get converted to 127.0.0.1:8080.

Solution

Adds a new "Local Gateway URL" setting that allows users to override the gateway URL used by the WebUI.

Priority order for gateway URL:

  1. User-configured Local Gateway URL (new)
  2. Gateway address from Kubo config
  3. Public Gateway (fallback)

Changes

  • Added LocalGatewayForm component in Settings
  • Added ipfsLocalGateway localStorage key
  • Modified selectGatewayUrl to check local override first
  • Sync setting to kuboGateway format for IPLD Explore page compatibility

How to Use

  1. Go to SettingsLocal Gateway
  2. Enter your actual gateway URL (e.g., https://ipfs.example.com)
  3. Submit - downloads and previews will now use this URL

Leave empty to use the existing behavior (auto-detect from Kubo config).

Testing

  • All Settings e2e tests pass
  • Manually tested with Docker + reverse proxy setup
  • Backward compatible - no change when setting is empty

Adds a new 'Local Gateway URL' setting that allows users to override
the gateway address from Kubo config. This is useful when:
- Running Kubo in Docker
- Accessing WebUI through a reverse proxy
- Accessing from a different host than where Kubo runs

The setting takes priority over the Kubo config gateway address.
When empty, the behavior falls back to the existing logic.

Fixes ipfs#2458
Ensures URLs like 'https://example.com/' and 'https://example.com'
are handled the same way, avoiding double slashes when constructing
paths like /ipfs/CID.
The ipld-explorer-components (Explore page) uses localStorage key
'kuboGateway' with {host, port, protocol} format. This change syncs
our 'ipfsLocalGateway' setting to that format so the Explore page
also uses the correct gateway URL.

Fixes Explore page using 127.0.0.1:8080 instead of custom gateway.
…flakiness

The e2e test uses getByText('Addresses') which matches any element
containing 'address' (case-insensitive). Changed 'gateway address' to
'gateway URL' in the description to avoid matching this query.
@gammazero

Copy link
Copy Markdown
Contributor

Triage: Will look at in conjunction with kubo v0.42.0

@GZGavinZhao

GZGavinZhao commented Apr 20, 2026

Copy link
Copy Markdown

I'd like to note that this fix is not just helpful for people using reverse proxy and Docker, but also anyone who doesn't set Addresses.Gateway to the default /ip4/127.0.0.1/tcp/8080. For example, I set my gateway port as 9090 because 8080 is used by some other application, and then WebUI refuses to "Explore" any CID because it tries to connect to http://127.0.0.1:8080/ipfs/<CID>.

The Local Gateway URL only reached download links, so previews,
thumbnails and IPNS links still used the public gateway behind a
reverse proxy. Make the override apply to every gateway link the
WebUI builds.

- config: when an override is set, use it as the reachable gateway
  too, so previews, thumbnails, Explore and IPNS links honor it
- ipns-manager: use the available gateway URL, which also fixes a
  broken link before the gateway check has run
- gateway/ipfs-provider: one shared helper builds the Explore (Helia)
  gateway config from the override, and clearing the override resets it
- local-gateway-form: check the URL loads before saving so a typo
  cannot silently break links; the check now keeps the port
- settings: show the description above the input like the other
  gateway fields, link the gateway address to its Kubo docs, and use
  `http://localhost:8080` in the example
- tests: unit coverage for the override selection and the Helia config
  helper, plus an e2e that sets a Local Gateway URL and confirms it on
  the Status page

Closes ipfs#2383
@lidel
lidel force-pushed the fix/local-gateway-override branch from d734d65 to 83e21d5 Compare June 30, 2026 01:56

@lidel lidel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this, and for your patience while it sat.

I pushed a follow-up to your branch instead of sending you back for another round. It merges in latest main and:

  • extends the override to previews, thumbnails, the Explore page and IPNS links, which still pointed at the public gateway behind a reverse proxy because only the download path read it (this also closes #2383)
  • folds the duplicated kuboGateway sync into one helper, and resets it when the override is cleared
  • validates that the URL is reachable before saving, so a typo can't silently break links
  • moves the field description above the input to match the other gateway settings, with a couple of unit tests
  • adds e2e test to lock this down against regressions

If any of it doesn't match what you intended, let me know in a new issue / pr, but I'm going to merge so it is not missed in the next release :)

@lidel
lidel merged commit 6a4acab into ipfs:main Jun 30, 2026
13 checks passed
@lidel lidel changed the title Add Local Gateway URL setting for reverse proxy and Docker support feat(config): add Local Gateway URL for reverse proxy and Docker Jun 30, 2026
lidel added a commit that referenced this pull request Jun 30, 2026
The share modal's local links flow through selectGatewayUrl, so the
Local Gateway URL override added in #2486 reaches them. Subdomain links
are offered only for domain gateways, since subdomain gateways cannot
resolve on a bare IP such as 127.0.0.1.

- files.js: add getLocalLinks, deriving both links from the gateway url
  (host, port, scheme); gate the subdomain link to domain hosts and to
  CIDs that fit a 63-char DNS label; share filename and base32 logic
  with getShareableLink
- actions.js: build the local links via getLocalLinks
- share-modal: clear the subdomain choice when the local link is
  unchecked, so it cannot silently reapply
- protocol.ts: type the share-link result as ShareLinks, not string
lidel added a commit that referenced this pull request Jul 16, 2026
* feat: add local gateway URL options to share modal

allow copying local gateway links for use in external apps,
with optional localhost subdomain mode for web apps

- actions.js: doFilesShareLink returns local and subdomain links
- ShareModal: checkbox to toggle local link, nested checkbox for
  localhost subdomains, QR hidden in local mode
- Modals: passes new link variants to ShareModal
- en/files.json: added translation keys for new UI elements

* feat: honor gateway override in local links

The share modal's local links flow through selectGatewayUrl, so the
Local Gateway URL override added in #2486 reaches them. Subdomain links
are offered only for domain gateways, since subdomain gateways cannot
resolve on a bare IP such as 127.0.0.1.

- files.js: add getLocalLinks, deriving both links from the gateway url
  (host, port, scheme); gate the subdomain link to domain hosts and to
  CIDs that fit a 63-char DNS label; share filename and base32 logic
  with getShareableLink
- actions.js: build the local links via getLocalLinks
- share-modal: clear the subdomain choice when the local link is
  unchecked, so it cannot silently reapply
- protocol.ts: type the share-link result as ShareLinks, not string

* fix: loopback share links and error handling

Refine the local gateway share links so they resolve from other apps and
never leave the modal hanging when generation fails.

- files.js: a single loopback check in getLocalLinks drives both links,
  so the path link uses 127.0.0.1 (no DNS) and the subdomain link uses
  localhost (origins need a hostname); domain gateways and non-loopback
  IPs are left as-is
- modals: catch a failed link generation and show an error instead of a
  stuck "Generating..."
- en/files.json: add the error string; mark the plain link as HTTP

* feat: native share links by default

Share Link and Publish to IPNS copy native ipfs:// and ipns:// URIs
by default, with opt-in HTTP gateway links for cases that need them.

- add a Settings "Sharing IPFS Links" section to choose the link
  type: native, local path/subdomain, or public path/subdomain
- public gateways default to empty and are opt-in; a public option
  stays disabled until its URL is set, and clearing it reverts to
  native
- native URIs use canonical CIDv1: base32 for /ipfs, base36
  libp2p-key for /ipns; the same choice drives Publish to IPNS
- local links normalize loopback per type: 127.0.0.1 for path,
  localhost for subdomain
- remove online gateway reachability probes; previews, thumbnails,
  IPLD explorer and IPNS links load from the local gateway (override
  or Kubo config), never a third-party gateway unless configured
- consolidate the localhost to 127.0.0.1 subresource fix across
  previews, thumbnails, downloads, CAR links and pinning icons
- Explore links honor the configured gateways; a local gateway
  change refreshes previews at once and reloads the explorer on the
  next visit

* fix: local links must not use public gateway

Share modal and content links labeled as local could point at the
public path gateway when the Kubo config exposed no usable gateway
address. Local links draw from the local gateway only (user override
or Kubo config), with related fixes and cleanups:

- loopback host rewrites apply to http only, so an https://localhost
  gateway keeps its certificate-valid hostname
- a link type without its gateway resolves to native before building,
  removing per-caller fallbacks in share and publish flows
- open-in-new-tab links (file preview, IPNS keys) honor the local
  subdomain choice from Settings for per-CID origin isolation
- pinning service icons resolve against the current gateway at read
  time and are omitted when no gateway is configured; previews and
  thumbnails skip gateway embeds in the same case
- shared toLoopbackIpUrl and GatewayForm replace per-site localhost
  rewrites and three near-identical gateway forms
- re-saving an unchanged Local Gateway URL no longer schedules an
  Explore page reload

* fix: keep existing public gateway defaults

keep the defaults users already have (ipfs.io path gateway, dweb.link
subdomain gateway, share links on dweb.link) so this PR can merge
without changing any default behavior. defaulting to native ipfs://
sharing is left for a follow-up: DEFAULT_SHARE_LINK_TYPE and the
DEFAULT_*_GATEWAY constants are the only knobs to flip.

- a gateway cleared in Settings stays cleared across reloads; only a
  never-written setting gets the default
- selecting a public link type persists the gateway it points at, so an
  explicit opt-in keeps its gateway if the defaults change later
ipfs-gui-bot pushed a commit that referenced this pull request Jul 16, 2026
## [4.13.0](v4.12.0...v4.13.0) (2026-07-16)

 CID `bafybeiciqeyipumpmhxzlxnbqdbbv6u5uij4hy4wax64dmj7kvrhusiq6y`

 ---

### Features

* choose share link type, add native uris ([#2482](#2482)) ([bbd8a31](bbd8a31)), closes [#2486](#2486)
* **config:** add Local Gateway URL for reverse proxy and Docker ([#2486](#2486)) ([6a4acab](6a4acab)), closes [#2458](#2458) [#2383](#2383)

### Bug Fixes

* **files:** unpin option missing in batch delete ([#2488](#2488)) ([d87d88b](d87d88b)), closes [ipfs/ipfs-desktop#3134](https://github.com/ipfs/ipfs-desktop/issues/3134)
* **ipns:** surface publish errors to user ([#2493](#2493)) ([5cdb301](5cdb301)), closes [#2492](#2492)

### Trivial Changes

* pull transifex translations ([#2483](#2483)) ([9037406](9037406))
* pull transifex translations ([#2491](#2491)) ([2007bd8](2007bd8))
* pull transifex translations ([#2495](#2495)) ([78ce01a](78ce01a))
@ipfs-gui-bot

Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 4.13.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

5 participants