docs: add production deployment guidance for gateway (#11117)
- add "Running in Production" section to gateway.md - link to specs.ipfs.tech instead of github - update "Protocol Labs" to "IPFS Foundation" - add reverse proxy requirement to config.md PublicGateways section - reference reverse proxy, timeout, rate limiting, and CDN caveats
Marcin Rataj committed
Jan 9, 2026 at 18:26 UTC
3e85793b5809dd56e6be5789ccbbaca23dc906ab
2 files changed
+110
-9
docs/config.md
+19
-1
@@ -1073,7 +1073,11 @@ Toggle and configure experimental features of Kubo. Experimental features are li
1073
1074
Options for the HTTP gateway.
1075
1076
-**NOTE:** support for `/api/v0` under the gateway path is now deprecated. It will be removed in future versions: <https://github.com/ipfs/kubo/issues/10312>.
1076
+> [!IMPORTANT]
1077
+> By default, Kubo's gateway is configured for local use at `127.0.0.1` and `localhost`.
1078
+> To run a public gateway, configure your domain names in [`Gateway.PublicGateways`](#gatewaypublicgateways).
1079
+> For production deployment considerations (reverse proxy, timeouts, rate limiting, CDN),
1080
+> see [Running in Production](gateway.md#running-in-production).
1081
1082
### `Gateway.NoFetch`
1083
@@ -1268,6 +1272,11 @@ Examples:
1272
- `*.example.com` will match requests to `http://foo.example.com/ipfs/*` or `http://{cid}.ipfs.bar.example.com/*`.
1273
- `foo-*.example.com` will match requests to `http://foo-bar.example.com/ipfs/*` or `http://{cid}.ipfs.foo-xyz.example.com/*`.
1274
1275
+> [!IMPORTANT]
1276
+> **Reverse Proxy:** If running behind nginx or another reverse proxy, ensure
1277
+> `Host` and `X-Forwarded-*` headers are forwarded correctly.
1278
+> See [Reverse Proxy Caveats](gateway.md#reverse-proxy) in gateway documentation.
1279
+
1280
#### `Gateway.PublicGateways: Paths`
1281
1282
An array of paths that should be exposed on the hostname.
@@ -1334,6 +1343,9 @@ Default: `false`
1343
1344
Type: `bool`
1345
1346
+> [!IMPORTANT]
1347
+> See [Reverse Proxy Caveats](gateway.md#reverse-proxy) if running behind nginx or another reverse proxy.
1348
+
1349
#### `Gateway.PublicGateways: NoDNSLink`
1350
1351
A boolean to configure whether DNSLink for hostname present in `Host`
@@ -1344,6 +1356,9 @@ Default: `false` (DNSLink lookup enabled by default for every defined hostname)
1356
1357
Type: `bool`
1358
1359
+> [!IMPORTANT]
1360
+> See [Reverse Proxy Caveats](gateway.md#reverse-proxy) if running behind nginx or another reverse proxy.
1361
+
1362
#### `Gateway.PublicGateways: InlineDNSLink`
1363
1364
An optional flag to explicitly configure whether subdomain gateway's redirects
@@ -1411,6 +1426,9 @@ ipfs config --json Gateway.PublicGateways '{"localhost": null }'
1426
1427
Below is a list of the most common gateway setups.
1428
1429
+> [!IMPORTANT]
1430
+> See [Reverse Proxy Caveats](gateway.md#reverse-proxy) if running behind nginx or another reverse proxy.
1431
+
1432
- Public [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.dweb.link` (each content root gets its own Origin)
1433
1434
```console
docs/gateway.md
+91
-8
@@ -6,7 +6,7 @@ they were stored in a traditional web server.
6
7
[More about Gateways](https://docs.ipfs.tech/concepts/ipfs-gateway/) and [addressing IPFS on the web](https://docs.ipfs.tech/how-to/address-ipfs-on-web/).
8
9
-Kubo's Gateway implementation follows [ipfs/specs: Specification for HTTP Gateways](https://github.com/ipfs/specs/tree/main/http-gateways#readme).
9
+Kubo's Gateway implementation follows [IPFS Gateway Specifications](https://specs.ipfs.tech/http-gateways/) and is tested with [Gateway Conformance Test Suite](https://github.com/ipfs/gateway-conformance).
10
11
### Local gateway
12
@@ -14,14 +14,21 @@ By default, Kubo nodes run
14
a [path gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway) at `http://127.0.0.1:8080/`
15
and a [subdomain gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://localhost:8080/`.
16
17
-The path one also implements [trustless gateway spec](https://specs.ipfs.tech/http-gateways/trustless-gateway/)
18
-and supports [trustless responses](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval) as opt-in via `Accept` header.
17
+> [!CAUTION]
18
+> **For browsing websites, web apps, and dapps in a browser, use the subdomain
19
+> gateway** (`localhost`). Each content root gets its own
20
+> [web origin](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy),
21
+> isolating localStorage, cookies, and session data between sites.
22
+>
23
+> **For file retrieval, use the path gateway** (`127.0.0.1`). Path gateways are
24
+> suited for downloading files or fetching [verifiable](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval)
25
+> content, but lack origin isolation (all content shares the same origin).
26
27
Additional listening addresses and gateway behaviors can be set in the [config](#configuration) file.
28
29
### Public gateways
30
24
-Protocol Labs provides a public gateway at
31
+IPFS Foundation [provides public gateways](https://docs.ipfs.tech/concepts/public-utilities/) at
32
`https://ipfs.io` ([path](https://specs.ipfs.tech/http-gateways/path-gateway/)),
33
`https://dweb.link` ([subdomain](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway)),
34
and `https://trustless-gateway.link` ([trustless](https://specs.ipfs.tech/http-gateways/trustless-gateway/) only).
@@ -41,6 +48,80 @@ The gateway's log level can be changed with this command:
48
> ipfs log level core/server debug
49
```
50
51
+## Running in Production
52
+
53
+When deploying Kubo's gateway in production, be aware of these important considerations:
54
+
55
+<a id="reverse-proxy"></a>
56
+> [!IMPORTANT]
57
+> **Reverse Proxy:** When running Kubo behind a reverse proxy (such as nginx),
58
+> the original `Host` header **must** be forwarded to Kubo for
59
+> [`Gateway.PublicGateways`](config.md#gatewaypublicgateways) to work.
60
+> Kubo uses the `Host` header to match configured hostnames and detect
61
+> subdomain gateway patterns like `{cid}.ipfs.example.org` or DNSLink hostnames.
62
+>
63
+> If the `Host` header is not forwarded correctly, Kubo will not recognize
64
+> the configured gateway hostnames and requests may be handled incorrectly.
65
+>
66
+> If `X-Forwarded-Proto` is not set, redirects over HTTPS will use wrong protocol
67
+> and DNSLink names will not be inlined for subdomain gateways.
68
+>
69
+> Example: minimal nginx configuration for `example.org`
70
+>
71
+> ```nginx
72
+> server {
73
+> listen 80;
74
+> listen [::]:80;
75
+>
76
+> # IMPORTANT: Include wildcard to match subdomain gateway requests.
77
+> # The dot prefix matches both apex domain and all subdomains.
78
+> server_name .example.org;
79
+>
80
+> location / {
81
+> proxy_pass http://127.0.0.1:8080;
82
+>
83
+> # IMPORTANT: Forward the original Host header to Kubo.
84
+> # Without this, PublicGateways configuration will not work.
85
+> proxy_set_header Host $host;
86
+>
87
+> # IMPORTANT: X-Forwarded-Proto is required for correct behavior:
88
+> # - Redirects will use https:// URLs when set to "https"
89
+> # - DNSLink names will be inlined for subdomain gateways
90
+> # (e.g., /ipns/en.wikipedia-on-ipfs.org → en-wikipedia--on--ipfs-org.ipns.example.org)
91
+> proxy_set_header X-Forwarded-Proto $scheme;
92
+> proxy_set_header X-Forwarded-Host $host;
93
+> }
94
+> }
95
+> ```
96
+>
97
+> Common mistakes to avoid:
98
+>
99
+> - **Missing wildcard in `server_name`:** Using only `server_name example.org;`
100
+> will not match subdomain requests like `{cid}.ipfs.example.org`. Always
101
+> include `*.example.org` or use the dot prefix `.example.org`.
102
+>
103
+> - **Wrong `Host` header value:** Using `proxy_set_header Host $proxy_host;`
104
+> sends the backend's hostname (e.g., `127.0.0.1:8080`) instead of the
105
+> original `Host` header. Always use `$host` or `$http_host`.
106
+>
107
+> - **Missing `Host` header entirely:** If `proxy_set_header Host` is not
108
+> specified, nginx defaults to `$proxy_host`, which breaks gateway routing.
109
+
110
+> [!IMPORTANT]
111
+> **Timeouts:** Configure [`Gateway.RetrievalTimeout`](config.md#gatewayretrievaltimeout)
112
+> based on your expected content retrieval times.
113
+
114
+> [!IMPORTANT]
115
+> **Rate Limiting:** Use [`Gateway.MaxConcurrentRequests`](config.md#gatewaymaxconcurrentrequests)
116
+> to protect against traffic spikes.
117
+
118
+> [!IMPORTANT]
119
+> **CDN/Cloudflare:** If using Cloudflare or other CDNs with
120
+> [deserialized responses](config.md#gatewaydeserializedresponses) enabled, review
121
+> [`Gateway.MaxRangeRequestFileSize`](config.md#gatewaymaxrangerequestfilesize) to avoid
122
+> excess bandwidth billing from range request bugs. Cloudflare users may need additional
123
+> protection via [Cloudflare Snippets](https://github.com/ipfs/boxo/issues/856#issuecomment-3523944976).
124
+
125
## Directories
126
127
For convenience, the gateway (mostly) acts like a normal web-server when serving
@@ -53,7 +134,7 @@ a directory:
134
2. Dynamically build and serve a listing of the contents of the directory.
135
136
<sub><sup>†</sup>This redirect is skipped if the query string contains a
56
-`go-get=1` parameter. See [PR#3964](https://github.com/ipfs/kubo/pull/3963)
137
+`go-get=1` parameter. See [PR#3963](https://github.com/ipfs/kubo/pull/3963)
138
for details</sub>
139
140
## Static Websites
@@ -107,10 +188,12 @@ This is equivalent of `ipfs block get`.
188
189
### `application/vnd.ipld.car`
190
110
-Returns a [CAR](https://ipld.io/specs/transport/car/) stream for specific DAG and selector.
191
+Returns a [CAR](https://ipld.io/specs/transport/car/) stream for a DAG or a subset of it.
192
112
-Right now only 'full DAG' implicit selector is implemented.
113
-Support for user-provided IPLD selectors is tracked in https://github.com/ipfs/kubo/issues/8769.
193
+The `dag-scope` parameter controls which blocks are included: `all` (default, entire DAG),
194
+`entity` (logical unit like a file), or `block` (single block). For [UnixFS](https://specs.ipfs.tech/unixfs/) files,
195
+`entity-bytes` enables byte range requests. See [IPIP-402](https://specs.ipfs.tech/ipips/ipip-0402/)
196
+for details.
197
198
This is a rough equivalent of `ipfs dag export`.
199