子目录中带有 Etherpad 的 nginx

nginx with Etherpad in a subdirectory

我正在 this location.

的子目录中设置 etherpad-lite

很遗憾,'static' 中的文件未加载:

很明显我的 nginx 中发生了一些事情,(部分)看起来像这样:

map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    
    server {
        listen       80;
        listen       [::]:80;
        server_name  _
    return 301 https://$server_name$request_uri;
}


    server {
        listen       443 ssl;
        server_name  www.whitewaterwriters.com;
    ssl_certificate /etc/letsencrypt/live/www.whitewaterwriters.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.whitewaterwriters.com/privkey.pem;
    return 301 https://whitewaterwriters.com$request_uri;
}
    
server {
    listen 443 ssl; 
    server_name whitewaterwriters.com;

    ssl_certificate /etc/letsencrypt/live/whitewaterwriters.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/whitewaterwriters.com/privkey.pem;
        root         /usr/share/nginx/html;
        index index.html index.php;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

    location ~ \.php$ {
    fastcgi_pass    unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_index   index.php;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include         fastcgi_params;
}


    location ~/watchtower/.*/live/pdfs/ {
        autoindex on;
    }

    location /watchtower {
        root /usr/share/nginx/html/;
    }


 location /etherpad {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  Host $host;
    proxy_redirect off;
    proxy_read_timeout 300;
    proxy_pass http://localhost:9001/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
  
    location /{
        root /usr/share/nginx/html/whitewaterwriters-site/_site/;
    }


        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

我的问题是:如何配置 nginx 才能显示丢失的文件?

在 github issues 和 SE 中还有一些关于这个主题的其他问题,但一般来说,它们是通过从 etherpad 转移到 etherpad-lite 来解决的,我已经在使用它,或者两者都是未回答且接近十年...

您可以尝试将静态内容导航到正确的文件夹:

location /static {
     root root /usr/share/nginx/html/whitewaterwriters-site/_site/static;
}

# or something like:

location /etherpad/static {
     root root /usr/share/nginx/html/whitewaterwriters-site/_site/;
}

因为这是有效的:https://whitewaterwriters.com/etherpad/static/js/vendors/html10n.js?v=869d568c

简短回答:如果您在前缀位置添加尾部斜杠,一切都会按预期进行。

map $http_upgrade $connection_upgrade {
    ''      close;
    default upgrade;
}
server {
    ...
    location /etherpad/ {
        proxy_buffering off; # recommended by etherpad nginx hosting examples
        proxy_set_header Host $host;
        # optional headers
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
        proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
        # recommended with keepalive connections
        proxy_http_version 1.1;
        # WebSocket support
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        # upstream
        proxy_pass http://127.0.0.1:9001/;
    }
}

如果您希望 /etherpad URI 也能正常工作,如果您无法使用上述配置将 HTTP 301 重定向到 /etherpad/etherpad/,请添加以下位置:

    location = /etherpad {
        return 301 /etherpad/;
    }

对我来说没有必要,但这取决于您的服务器环境。

要保留查询字符串(如果有),您可以使用 return 301 /etherpad/$is_args$args;rewrite ^ /etherpad/ permanent


长答案(以及卧底发生的事情)。

SO 上有很多关于 “我如何在 URI 前缀下托管 Web 应用程序”的问题Here is one on my answers and here 是关于类似主题的 ServerFault 线程。

唯一正确的方法是让您的代理应用仅通过相对 URI 请求其资产(考虑 assets/script.js 而不是 /assets/script.js)或使用正确的 URI前缀 (/etherpad/assets/script.js).

幸运的是,etherpad 使用相对路径(例如 <script src="static/js/index.js"></script>)请求其资产,使其适合在任何 URI 前缀下托管。问题是,当你的原始 URI 是 /etherpad 时,浏览器将当前远程 Web 服务器目录视为根目录,并从服务器请求上述脚本作为 scheme://domain/static/js/index.js。该请求甚至不会被您的 location /etherpad { ... } 捕获(因为它不是以 /etherpad 开头)。另一方面,当您的源 URI 是 /etherpad/ 时,浏览器将当前远程 Web 服务器目录视为 /etherpad/ 并正确地从服务器请求上述脚本 scheme://domain/etherpad/static/js/index.js.

现在让我们看看使用您的原始配置代理请求 /etherpad/<path> 发生了什么。由于您在上游地址 (http://localhost + /) 后使用尾部斜杠,nginx 从请求 URI 中删除位置 /etherpad 前缀,并在其前面加上该斜杠(或任何其他 URI)在上游名称后的 proxy_pass 指令中使用)导致 //<path>。您可以阅读 A little confused about trailing slash behavior in nginx or nginx and trailing slash with proxy pass SO 线程以了解更多详细信息。无论如何,Etherpad 不会提供 URI 给你 Cannot GET //<path> 错误。

location /etherpad { ... } 更改为 location /etherpad/ { ... } 您将解决上述两个问题。


关于 etherpad 的几句话 wiki examples, especially this one

两者

location /etherpad/ {
    proxy_pass http://127.0.0.1/;
    ...
}

location /etherpad/ {
    rewrite ^/etherpad(/.*)  break;
    proxy_pass http://127.0.0.1;
    ...
}

执行相同的字符串 - 在将请求 URI 传递给上游之前从请求 URI 中剥离 /etherpad 前缀。然而,第一个以更有效的方式做到这一点。最好尽可能避免使用正则表达式。使用

location = /etherpad {
    return 301 /etherpad/;
}

也比

更有效率
rewrite ^/etherpad$ /etherpad/ permanent;

上述 wiki 示例中的第二个和第三个位置块完全重复了第一个的功能。此外,该示例破坏了 WebSocket support(无论是谁编写的,他至少可以将该支持添加到 location /pad/socket.io { ... } 块)。

永远不要做 this 示例中使用的事情:

location ~ ^/$ { ... }

改为使用完全匹配的位置:

location = / { ... }

这是我测试过的另一种配置,目的是检查我是否可以直接通过 nginx 提供 etherpad 静态资产。它似乎是可行的,尽管我没有对其进行大量测试。它使用未压缩的 js/css 资产版本(当您使用 gzip 或其他一些压缩时,这应该不会影响性能)。这也是一个很好的配置示例,您无法避免使用 rewrite 指令从请求 URI 中去除前缀​​。

    location /etherpad/static/ {
        # trying to serve assets directly via nginx
        # if the asset is not found, pass the request to the nodejs upstream
        rewrite ^/etherpad(/.*)  break;
        root /full/path/to/etherpad-lite/src;
        try_files $uri @etherpad;
    }
    location /etherpad/ {
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001/;
    }
    location @etherpad {
        proxy_redirect / /etherpad/;
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001;
    }

更新

作为 GitHub 上的 suggested,以 /etherpad/static/plugins/ 前缀开头的 URI 应始终传递给 nodejs 上游,因为 [=51] 下不存在相应的资产=] 目录。尽管已经定义了回退到 nodejs 上游(try_files $uri @etherpad),为了消除由 try_files 指令产生的额外 stat 系统调用,我们可以将上面的配置修改为:

    location ~ ^/etherpad/static/(?!plugins/) {
        # trying to serve assets directly via nginx
        # if the asset is not found, pass the request to the nodejs upstream
        rewrite ^/etherpad(/.*)  break;
        root /full/path/to/etherpad-lite/src;
        try_files $uri @etherpad;
    }
    location /etherpad/ {
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001/;
    }
    location @etherpad {
        proxy_redirect / /etherpad/;
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001;
    }

(使用负前瞻性正则表达式,更好的可读性)或这个:

    location /etherpad/ {
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001/;
    }
    location /etherpad/static/ {
        rewrite ^/etherpad(/.*)  break;
        root /full/path/to/etherpad-lite/src;
        try_files $uri @etherpad;
    }
    location /etherpad/static/plugins/ {
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001/static/plugins/;
    }
    location @etherpad {
        proxy_redirect / /etherpad/;
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_http_version 1.1;
        proxy_pass http://127.0.0.1:9001;
    }

(仅前缀位置,性能更好)。重复部分

proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;

可能还有其他可选的 headers (X-Real-IP, X-Forwarded-For, X-Forwarded-Proto) 答案开头提到的设置,可以用作单独的文件,例如etherpad-proxy.conf,并使用 include 指令包含在主 nginx 配置中。