What these configs do:
- Proxy all traffic from Notion to your custom domain
notion.example.tld
and deliver it to your clients - WebSocket proxy support
- Image local disk caching support
- Correct URL rewriting
- Get access logs from real request IPs
This post is a proof of concept proxying a general XaaS without using any vendor-locked FaaS such as Cloudflare Workers or AWS Lambda.
Main origin Nginx config:
# Notion Proxy
server {
listen 80;
listen [::]:80;
server_name notion.example.tld notion-origin.example.tld;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name notion.example.tld notion-origin.example.tld;
# Certificate
ssl_certificate /root/.acme.sh/example.tld_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/example.tld_ecc/example.tld.key;
ssl_stapling on;
ssl_stapling_verify on;
# Longer resolver timeout
# https://stackoverflow.com/a/26833369/412385
resolver_timeout 30s;
# Hide unwanted headers
proxy_hide_header Content-Security-Policy;
proxy_hide_header Expect-CT;
location / {
proxy_pass https://www.notion.so;
proxy_set_header Referer https://www.notion.so/;
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_set_header Accept-Encoding "";
sub_filter 'www.notion.so' 'notion.example.tld';
sub_filter_last_modified on;
sub_filter_types *;
sub_filter_once off;
# Replace cookie domain
proxy_cookie_domain www.notion.so notion.example.tld;
# Rewrite common redirects
proxy_redirect ~*https??://www.notion.so(.*)$ https://notion.example.tld$1;
# Caching images
set $use_proxy_cache off;
if ($uri ~* ^/image) {
set $use_proxy_cache main_disk;
}
proxy_cache $use_proxy_cache;
proxy_cache_valid 200 304 1M;
proxy_cache_valid 301 302 15m;
proxy_cache_valid any 1m;
break;
}
}
server {
listen 80;
listen [::]:80;
server_name msgstore.notion.example.tld msgstore.notion-origin.example.tld;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name msgstore.notion.example.tld msgstore.notion-origin.example.tld;
# Certificate
ssl_certificate /root/.acme.sh/example.tld_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/example.tld_ecc/example.tld.key;
ssl_stapling on;
ssl_stapling_verify on;
# Longer resolver timeout
# https://stackoverflow.com/a/26833369/412385
resolver_timeout 30s;
location / {
proxy_pass https://msgstore.www.notion.so;
proxy_set_header Referer https://www.notion.so/;
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
# Replace cookie domain
proxy_cookie_domain www.notion.so msgstore.notion.example.tld;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache off;
break;
}
}
Proxy CDN node:
server {
listen 80;
listen [::]:80;
server_name notion.example.tld;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name notion.example.tld;
# Certificate
ssl_certificate /root/.acme.sh/example.tld_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/example.tld_ecc/example.tld.key;
ssl_stapling on;
ssl_stapling_verify on;
# Global proxy settings
proxy_hide_header Vary;
# Add location header
add_header X-EbS-Edge-Cache $upstream_cache_status;
# Global cache size increase
proxy_buffers 8 32k;
proxy_buffer_size 64k;
location / {
proxy_pass https://notion-origin.example.tld;
proxy_buffering on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Enable the following if `proxy_pass` to a https protocol
proxy_set_header X-Forwarded-Proto https;
# Caching images
set $use_proxy_cache off;
if ($uri ~* ^/image) {
set $use_proxy_cache main_disk;
}
proxy_cache $use_proxy_cache;
}
}
server {
listen 80;
listen [::]:80;
server_name msgstore.notion.example.tld;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name msgstore.notion.example.tld;
# Certificate
ssl_certificate /root/.acme.sh/example.tld_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/example.tld_ecc/example.tld.key;
ssl_stapling on;
ssl_stapling_verify on;
# Global proxy settings
proxy_hide_header Vary;
# Add location header
add_header X-EbS-Edge-Cache $upstream_cache_status;
# Global cache size increase
proxy_buffers 8 32k;
proxy_buffer_size 64k;
location / {
proxy_pass https://msgstore.notion-origin.example.tld;
proxy_buffering on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache off;
}
}
The CDN node acts as a external reverse proxy that can proxy traffic and deliver it to the nearest users.