一次用 Nginx 来绑定个人域名到 Notion 的折腾

Notion.so 是一个备受瞩目的笔记产品。由于提供了丰富的样式及功能,许多人都用它来实现各种内容类的功能,笔记、日程、代办、任务看板、CRM、Wiki 等等。当然还有博客。但是一个不能绑定个人域名的博客工具,总是缺少了一些 hack 的乐趣。于此,要介绍一下使用 Nginx 来实现绑定个人域名到 Notion 的效果。

如果搜索一下的话会发现,市面上现在提供类似效果的,借助的都是 Cloudflare。方案看下来,一则是麻烦,且有牛刀杀鸡的感觉,二是感觉提供的效果,应该是可以用服务端应用来实现的,比如 Nginx 的反向代理等等,没必要额外再新增一个不熟悉的服务。碰巧我的 VPS 上就装了 Nginx,也用它配置了一些服务,于是便摸索试着用 Nginx 来配置。

基础的想法都是将个人域名重定向到 Notion 里面一个公开的特定页面上,同时 URL 不变。Notion 的单页面的 URL 结构都是诸如 notion.so/path-to-the-file-rfq32ravqatfeqf4f 这般,我试图用域名 xubihang.name 直接反代这个页面,结果无论我怎么配置,最终的效果都是成功跳转同时 URL 也发生了变化。而我又对 Nginx 配置不熟,而且对 Nginx 总有一种缺乏最佳实践的赌气心理而没有深入看过文档,于是陷入僵局。

在我断断续续折腾了一周之后,在 GitHub 的一个角落里面找到了曙光。这个 Repo:lobre/docker-notion-proxy 是一个 docker 的配置信息,用来实现个人域名绑定的效果。其中的 readme 解释了为什么直接绑定是不行的:

We cannot hide/rewrite the URL for a clean root domain.
For the What’s New public page for instance, we cannot have it directly under http://example.com. We need the appended URI: http://example.com/What-s-New-157765353f2c4705bd45474e5ba8b46c.
The reason is that Notion relies a lot on Javascript. The routing to a public page seems to be done dynamically using Javascript with window.location.href (actual browser URL) to parse which page should be displayed. So when pointing to http://example.com, it will understand that it should display http://www.notion.so even if we proxy_pass to a custom page.
In order to still have a special page attached to the root domain, you can add the REDIRECT environment variable to set up a redirection on the root domain. So with our example after having set REDIRECT=What-s-New-157765353f2c4705bd45474e5ba8b46c, hitting http://example.com will 302 redirect to http://example.com/What-s-New-157765353f2c4705bd45474e5ba8b46c.

……行吧。于是照着里面的配置项,整理了一下 Nginx 下的配置。具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
server_name yourdomain.com;
location / {
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
rewrite ^/$ http://yourdomain.com/the-gibberish-url-direct-to-the-notion-page-fewafedawfedfa;
proxy_pass https://www.notion.so;
proxy_set_header Host www.notion.so;
proxy_set_header Referer https://www.notion.so;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language $http_accept_language;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
sub_filter https://www.notion.so https://yourdomain.com;
sub_filter_once off;
sub_filter_types application/javascript;
proxy_ssl_server_name on;
}

Repo里面的配置项没有这个:

1
2
3
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;

起初没加,结果发现域名点开 404。后来看了一下 Nginx 的报错日志,Google 了一番原因,发现是反代默认的 buffer 太小,页面太大就失败了。增大之后就不存在该问题。另外还有可能出现的一个问题是 Nginx 服务无法访问某些目录导致无法成功加载,这个的话只要把对应目录的权限开放给启动 Nginx 的用户,或者简单粗暴直接把启动用户设置为 root 就可以解决。

至此域名已经绑定成功。可以体验我 host 在 Notion.so 的个人主页