IPFS Gateway 部署指南

IPFS 官方还没有很完整的 Gateway 部署指南,而且 Gateway 也缺少 Authorization 支持,本文就是简单记录下 Gateway 的部署过程,分别使用 Nginx 与 Caddy 作为服务器软件,最终将会得到:

  • 基于 Docker 部署的 IPFS 实例;
  • 支持 HTTPS 的 Gateway;
  • 支持 HTTP Basic Authentication 的 API Server;

在开始前,你需要提前准备以下几项内容:

  1. 知道一些基本操作,或者会找相关的资料学习解决。比如如何安装 Docker Compose 等,我在此不会涉及太多这些内容。
  2. 一台云服务器主机。例如我在 Vultr 临时创建了一个系统为 Ubuntu 22.04 的实例用作演示,价格为 $6/月。
  3. 一个域名。例如我用来演示的域名托管在 Cloudflare 上。下文统一使用 your.domain 指代这个域名。小技巧:可以使用 Chrome 扩展 FindR 来替换 your.domain 成你自己的域名使得阅读与复制更加方便。

1. Docker 部署 IPFS

首先在云服务器 Ubuntu 上安装好 docker 与 docker-compose,然后执行以下操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1. 创建并切换到工作目录
mkdir ipfs && cd ipfs

# 2. 创建 docker-compose.yml
echo "
version: '3'
services:
ipfs:
container_name: kubo
image: ipfs/kubo:latest
restart: unless-stopped
volumes:
- ./ipfs:/data/ipfs
- ./ipfs_fuse:/ipfs
- ./ipns_fuse:/ipns
environment:
- IPFS_PATH=/data/ipfs
ports:
- 4001:4001/tcp
- 4001:4001/udp
- 127.0.0.1:5001:5001
- 127.0.0.1:8080:8080
" > docker-compose.yml

# 3. 运行 docker-compose 版本的 IPFS 实例
docker-compose up -d

# 4. 检查是否成功
curl localhost:8080/ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme

现在 IPFS 实例已经部署完成了,现在我们修改一些 IPFS 的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 进入 IPFS 实例的 shell
docker exec -it kubo /bin/sh

# 2. 如果 IPFS 在日志中抱怨 system: cannot reserve inbound connection: resource limit exceeded 那可以尝试增加 ConnsInbound
ipfs config --json Swarm.ResourceMgr.Limits.System.ConnsInbound 2048

# 3. 配置 PublicGateway 域名,注意将 gateway.your.domain 替换成你自己的域名
ipfs config --json Gateway.PublicGateways '{
"gateway.your.domain": {
"UseSubdomains": true,
"InlineDNSLink": true,
"Paths": ["/ipfs", "/ipns"]
}
}'

# 4. 退出 shell,完成 IPFS 配置
exit

# 5. 重启 IPFS 实例,应用配置
docker-compose restart

然后,进行防火墙配置,我这里执行 ufw disable 关闭 UFW,改成使用云服务器提供的防火墙服务,你也可以直接使用系统内的防火墙。主要就是同时开启 IPv4 与 IPv6 的 TCP 22/80/443/4001 端口与 UDP 4001 端口,如下:

Action Protocol Port Source
accept SSH 22 0.0.0.0/0,::/0
accept TCP (HTTP) 80 0.0.0.0/0,::/0
accept TCP (HTTPS) 443 0.0.0.0/0,::/0
accept TCP 4001 0.0.0.0/0,::/0
accept UDP 4001 0.0.0.0/0,::/0
drop any 0 - 65535 0.0.0.0/0,::/0

2. DNS 配置

找到 Vultr 实例的 IP,比如我的分别为 IPv4: 149.28.140.214,IPv6: 2401:c080:1400:6016:5400:04ff:fe45:2010。那就在 your.domain 的 DNS 管理中添加以下几个记录,如果你是在 Cloudflare 中,暂时不要开启 Proxy:

Type Name Content
A gateway 149.28.140.214
A *.ipfs.gateway 149.28.140.214
A *.ipns.gateway 149.28.140.214
AAAA gateway 2401:c080:1400:6016:5400:04ff:fe45:2010
AAAA *.ipfs.gateway 2401:c080:1400:6016:5400:04ff:fe45:2010
AAAA *.ipns.gateway 2401:c080:1400:6016:5400:04ff:fe45:2010

3. Nginx 作为服务器

Nginx 是常用的服务器工具,下面介绍 Nginx 作为 IPFS 的服务器的配置。

3.1 Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 1. 安装 Nginx,在 Ubuntu 上可以使用
apt install nginx

# 3. 添加 gateway 的 Nginx conf 配置
echo '
server {
listen 80;
listen [::]:80;

server_name gateway.your.domain;

location /ipfs {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host gateway.your.domain;
}

location /ipns {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host gateway.your.domain;
}

location /api {
proxy_pass http://127.0.0.1:5001;
proxy_set_header Host gateway.your.domain;
}
}
' > /etc/nginx/conf.d/ipfsgateway.conf

echo '
server {
listen 80;
listen [::]:80;

server_name *.ipfs.gateway.your.domain;

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
}
' > /etc/nginx/conf.d/ipfsgateway_ipfs.conf

echo '
server {
listen 80;
listen [::]:80;

server_name *.ipns.gateway.your.domain;

location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
}
' > /etc/nginx/conf.d/ipfsgateway_ipns.conf

# 4. 检查并应用 Nginx 配置
nginx -t && nginx -s reload

访问 http://gateway.your.domain/ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme 查看 Nginx 是否配置成功。

3.2 HTTPS 证书生成

我们借助 Certbot 帮忙生成 HTTPS 证书,因为我们使用通配符子域名,自动配置时需要完成 DNS 挑战。首先在 Cloudflare 用户界面 创建一个权限为 Zone:DNS:Edit 的 API Token,“Zone Resources” 选择现在所用的域名,将生成的 Token 按照格式 dns_cloudflare_api_token = YOUR_API_TOKEN 写入文件 ~/.secrets/certbot/cloudflare.ini。 然后如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 调整权限
chmod 600 ~/.secrets/certbot/cloudflare.ini

# 2. 安装 certbot
snap install certbot --classic
snap set certbot trust-plugin-with-root=ok
snap install certbot-dns-cloudflare

# 3. 完成 DNS 挑战与 HTTPS 配置
certbot --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini --dns-cloudflare-propagation-seconds 20 \
--installer nginx \
-d gateway.your.domain \
-d *.ipfs.gateway.your.domain -d *.ipns.gateway.your.domain

最后,修改 ipfsgateway.conf,为 /ipns, /ipfs 两个 location 添加 proxy_set_header X-Forwarded-Proto "https";

1
2
3
4
5
6
7
8
9
10
11
location /ipfs {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host gateway.your.domain;
proxy_set_header X-Forwarded-Proto "https";
}

location /ipns {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host gateway.your.domain;
proxy_set_header X-Forwarded-Proto "https";
}

然后执行 nginx -t && nginx -s reload 以生效,这样 Gateway 在需要重定向时会自动重定向为 HTTPS。现在测试下下面的链接:

3.3 IPFS API Server 添加认证

默认的 IPFS API Server,不做认证,如果暴露在公网,则谁都可以访问,而且 IPFS 并没有提供相关的认证功能。所以我们在 Nginx 里为 API Server 添加 Basic Auth:

1
2
3
4
# 1. 安装相关工具
apt install apache2-utils
# 2. 生成默认密码文件,your_username 换成你的用户名
htpasswd -c /etc/nginx/.htpasswd your_username

然后修改 Nginx 配置,为 /api 添加 auth_basic 配置。

1
2
3
4
5
6
location /api {
auth_basic "Auth Required Area";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:5001;
proxy_set_header Host gateway.your.domain;
}

然后执行 nginx -t && nginx -s reload 以生效。然后可以测试如下命令,注意将 your_username 与 your_password 替换:

1
2
curl -X POST "https://gateway.your.domain/api/v0/cat?arg=/ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme" \
-H "Authorization: Basic $(echo -n 'your_username:your_password' | base64)"

4. Caddy 作为服务器

Caddy 能够自动生成 HTTPS 证书,且也可以实现 Basic Auth,所以这里整理下 Caddy 作为服务器的配置。

4.1 构建带有额外组件的 Caddy Docker 镜像

和 Nginx 中使用 Certbot 生成证书类似,由于我们需要使用通配子域名,也要安装额外的组件,Caddy 原始镜像不提供这个功能,需要自行构建,新建 Dockerfile 以及 docker-compose.yml 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 切换目录
mkdir caddy && cd caddy

# 添加了 cloudflare dns 组件的 caddy Dockerfile
echo `
FROM caddy:2.6.2-builder AS builder

RUN xcaddy build \
--with github.com/caddy-dns/cloudflare

FROM caddy:2.6.2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy
` > Dockerfile

# 注意:这里指定并会创建 caddy_network,用于之后共享给 IPFS 服务
echo `
version: "3"

services:
caddy:
build: .
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "80:80/udp"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data/:/data/caddy/
- ./config/:/config/caddy
networks:
- caddynet

networks:
caddynet:
name: caddy_network
` > docker-compose.yml

# 构建镜像
docker-compose build

然后在相同目录下创建 Caddyfile,注意替换其中的以下内容

  • 邮箱地址:用于证书生成
  • Cloudflare API Token:获取方法与 Nginx 配置中一致
  • Basic Auth 用户名和密码:用户名使用明文,密码可以在 caddy 服务启动后使用命令 docker exec -it caddy caddy hash-password 生成,见 basicauth - Caddy Documentation
  • 域名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
auto_https ignore_loaded_certs
email your@email.address
acme_dns cloudflare your_dns_cloudflare_api_token
}

gateway.your.domain {
handle /ipfs/* {
reverse_proxy kubo:8080 {
header_up HOST gateway.your.domain
header_up X-Forwarded-Proto "https"
}
}
handle /ipns/* {
reverse_proxy kubo:8080 {
header_up HOST gateway.your.domain
header_up X-Forwarded-Proto "https"
}
}
handle /api/* {
reverse_proxy kubo:5001 {
header_up HOST gateway.your.domain
}
}

basicauth /api/* {
your_username your_password
}
}

*.ipfs.gateway.your.domain {
handle * {
reverse_proxy kubo:8080 {
header_up HOST {host}
header_up X-Forwarded-Proto "https"
}
}
}

*.ipns.gateway.your.domain {
handle * {
reverse_proxy kubo:8080 {
header_up HOST {host}
header_up X-Forwarded-Proto "https"
}
}
}

现在可以使用 docker-compose up -d 启动 caddy 服务。

4.2 Caddy 访问 Kubo 服务

要使 Caddy 在 Docker 实例中能够访问 Kubo 服务,需要让 Kubo 加入 Caddy 的网络,只需要在 Kubo 的 docker-compose.yml 中添加 Caddy 的网络如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3'
services:
ipfs:
container_name: kubo
image: ipfs/kubo:latest
restart: unless-stopped
volumes:
- ./ipfs:/data/ipfs
- ./ipfs_fuse:/ipfs
- ./ipns_fuse:/ipns
environment:
- IPFS_PATH=/data/ipfs
ports:
- 4001:4001/tcp
- 4001:4001/udp
- 127.0.0.1:5001:5001
- 127.0.0.1:8080:8080
networks:
- ipfsnet

networks:
ipfsnet:
name: caddy_network
external: true

然后使用 docker-compose up -d --force-recreate 重新创建 Kubo 服务即可。

开启 Cloudflare Proxy 的问题

为了保护和加速网站的访问,首先你可以在 Cloudflare 为 gateway.your.domain 开启 Proxy。如果访问 Gateway 发生 ERR_TOO_MANY_REDIRECTS(xxx redirected you too many times) 错误,需要把域名的 SSL/TLS Encryption mode 配置从 Flexible 调整为 Full

Cloudflare 免费支持通配符,且免费为 *.your.domain 这样的通配二级域名子域名提供 HTTPS 证书,但是本文 Gateway 场景中需要为 *.ipfs.gateway.your.domain 通配四级域名子域名提供 HTTPS 证书,在 Cloudflare 中需要订阅 Advanced Certificate Manager 或者 Business Plan 才能实现自动生成或者自主上传涵盖这种子域名的高级证书。

此时如果强制为 *.ipfs.gateway 或者 *.ipns.gateway 开启 Proxy,会提示 This hostname is not covered by a certificate,访问时也会出现 ERR_SSL_VERSION_OR_CIPHER_MISMATCH(This site can’t provide a secure xxx uses an unsupported protocol.) 错误。

这类功能确实属于高级功能,作为普通用户如果不愿意付费也没有关系,选择不开启 Proxy 至此也能完全正常使用了。也可以在 IPFS PublicGateways 配置时将 UseSubdomains 改为 false,这样可以禁用不受保护的 ipfs 与 ipns 子域名,且不再重定向,代价就是这样的 URL 路径违反了同源策略(Same-origin policy)会造成一些兼容性问题。

Reference

  1. Hosting a public IPFS gateway
  2. IPFS Gateway | IPFS Docs
  3. Kubo Config - Gateway
  4. Restricting Access with HTTP Basic Authentication | NGINX Plus
  5. certbot-dns-cloudflare’s Documentation
  6. ERR_TOO_MANY_REDIRECTS · Cloudflare SSL/TLS docs
  7. ERR_SSL_VERSION_OR_CIPHER_MISMATCH · Cloudflare SSL/TLS docs

Powered by Hexo and Hiker

Copyright © 2018 - 2024 Velih's Blog All Rights Reserved.

Velih Dzen 保留所有权利