在现有网站子路径下安全托管 BookStack

希望把知识库放在 https://example.com/bookstack,并不等于要把整个 BookStack 安装目录塞进主站的公开目录。真正需要的是一个子路径入口:浏览器访问 /bookstack,服务器只把请求送到 BookStack 的 public 目录,应用根目录、环境配置和私有文件仍在公开目录之外。

本文依据 BookStack 官方 Subdirectory Setup 翻译整理,完整覆盖基础 URL、Apache 与 Nginx 两条配置路径。2026-10-05 核对原文,并补充安装页和安全页所列的版本、代理信任边界。适用对象是 Ubuntu 类系统的原生部署;Docker 部署需按容器网络和反向代理重新设计。下列配置只经过静态审核,没有修改服务器或执行重载。

浏览器经公网 HTTPS 的 /bookstack/ 入口进入本机回环 Nginx 后端,只访问 BookStack public 目录;.env 和 storage 留在非公开的应用目录。
图:未完纪绘制的子路径与文件公开边界示意。Apache 可用 Alias 直接映射 public;图中展示 Nginx 双 server 块方案。

先把安装目录与网址分开

假设现有网站的根目录是 /var/www/html,BookStack 安装在与其并列的 /var/www/bookstack。完成常规安装后,环境文件位于 /var/www/bookstack/.env。任何站点的 DocumentRoot、root 或其他别名,都不应直接暴露整个安装目录。尤其不能把它安装到 /var/www/html/bookstack 后,再期待几条子路径规则弥补全部私有文件暴露风险。

在 .env 中把外部基础地址写成实际访问 URL,末尾不加斜线:

APP_URL=https://example.com/bookstack

example.com 和 /bookstack 是示例域名与前缀,需要一起替换成自己的地址。此配置影响应用生成的链接,也限制它依赖传入 Host 生成错误 URL 的机会。修改前应保留现有配置和可回退版本,不要为子路径改造重新生成已有实例的 APP_KEY;它与加密数据、会话等功能有关。

Apache:把别名指向 public

原文假定已安装 Apache、PHP,并启用 mod_php。在 Ubuntu 类系统上还需启用 mod_rewrite:

sudo a2enmod rewrite

找到主站已有的虚拟主机配置,例如 /etc/apache2/sites-available/000-default.conf。在对应的 <VirtualHost> 内加入以下片段,不覆盖主站原有的域名、证书和其他路径规则。这里保留原文 Alias 与目录访问控制的结构,同时明确设置子路径重写基址。

# 放入已有站点的 VirtualHost 内;保留现有 HTTPS 证书等设置。
Alias "/bookstack" "/var/www/bookstack/public"

<Directory "/var/www/bookstack">
    AllowOverride None
    Require all denied
</Directory>

<Directory "/var/www/bookstack/public">
    Options FollowSymLinks
    AllowOverride None
    Require all granted
    RewriteEngine On
    RewriteBase /bookstack/

    # 修订:非目录的尾斜线重定向保留 /bookstack 前缀。
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /bookstack/$1 [L,R=301]

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</Directory>

Alias 的目标必须保留 /public。外层安装目录拒绝直接访问,public 子目录单独放行;存在的文件和目录按正常方式处理,其余请求交给 index.php 这个前端控制器。Options FollowSymLinks 没有启用目录索引。服务器还需限制谁能往可公开目录写文件或建立链接。

与原文的差异:原文删除尾斜线的替换目标为 /$1。在目录上下文中,规则匹配值通常已去掉该目录前缀,这种根路径替换存在跳出 /bookstack 的风险;本稿改为 /bookstack/$1 并显式设置 RewriteBase /bookstack/。换用 /docs 时,Alias、RewriteBase、重定向目标和 APP_URL 都要同步修改。本修订未做 Apache 实机验证,部署前应检查重定向链及不同路径情况。

Nginx:用本机后端保留应用的完整配置

原文的 Nginx 方案使用两个 server 块。内部块按站点根路径运行 BookStack;公网块接收 /bookstack/ 后,把前缀剥掉再代理给内部块。这样应用的 PHP 和静态文件规则可放在独立配置中,避免与主站混杂。

原例写的是 listen 8080 与 listen [::]:8080,虽然配了 server_name localhost,但服务器名称不是网络访问限制;这种监听写法可能让后端端口暴露在非回环接口。本稿将后端明确绑定到 127.0.0.1:8080。若端口已占用,需要统一修改监听与代理地址。

# 独立的后端 server 块,仅本机回环可访问。
server {
    listen 127.0.0.1:8080;
    server_name localhost;

    root /var/www/bookstack/public;
    index index.php;
    autoindex off;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        # 示例路径:先确认已安装的受支持 PHP-FPM 实际 socket。
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

# 以下两个 location 放入已有的公网 HTTPS server 块。
location = /bookstack {
    return 301 /bookstack/$is_args$args;
}
location ^~ /bookstack/ {
    proxy_pass http://127.0.0.1:8080/;
    proxy_redirect off;

    # 此例假定这里就是直接接收浏览器请求的边缘代理。
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;
}

两处结尾斜线有明确含义:location /bookstack/ 与 proxy_pass http://127.0.0.1:8080/ 配合,会把 /bookstack/books 转为后端的 /books。随手删除 proxy_pass 的尾斜线会改变转发 URI。新增的精确匹配用于把没有尾斜线的入口规范为 /bookstack/;^~ 则避免主站其他正则 location 抢走这个前缀下的请求。

版本修订:原文 PHP-FPM 路径是 /run/php/php7.4-fpm.sock,已不符合当前安装页要求。2026-10-05 的安装页列明 PHP ≥ 8.2。这里仅用 php8.3-fpm.sock 作为现代环境的路径示例,不表示每台机器都有这个 socket。必须核对已安装且受支持的 PHP 版本、FPM 配置与运行用户,再替换路径;不要为了适配旧教程降级到 PHP 7.4。

让代理身份与 HTTPS 信息保持可信

上面的公网块假定直接面对浏览器,因此用 $remote_addr 覆盖 X-Forwarded-For,而不是继续信任浏览器随意提交的同名头。它也把外部协议写到 X-Forwarded-Proto。若前面还有 CDN、负载均衡器或其他代理,必须按真实代理链配置,不能把此单跳示例直接当作多跳方案。

根据 BookStack 的 Trusted Proxies 文档,在本稿明确的本机代理结构下,可以只信任该回环代理:

APP_PROXIES=127.0.0.1

该项是本稿依据安全文档补充的配置,子目录原文没有展开。它允许应用使用可信代理传来的原始请求信息,影响审计日志和限流等功能。不要为排错长期设置 APP_PROXIES=*。若代理通过 IPv6 回环或其他地址连接,应以实际连接来源为准调整,同时确保后端无法被不可信客户端绕过访问。

检查通过后,再加载配置

原文分别给出重启 Apache、Nginx 的命令。本稿将语法检查放在前面,并建议在检查成功且具备维护窗口与回退办法后重载配置;新增模块等情形若要求重启,应按系统实际需求处理。以下是管理员应在目标测试环境执行的步骤,本次没有运行:

# Apache 路径
sudo apachectl configtest
# 仅当上一项通过后:
sudo systemctl reload apache2.service

# Nginx 路径
sudo nginx -t
# 仅当上一项通过后:
sudo systemctl reload nginx.service

浏览器访问目标子路径后,检查首页、登录、书架和页面链接、样式与图片是否都留在正确前缀下。测试带斜线和不带斜线的地址,查看 Location 响应头是否意外丢失前缀或回退到 HTTP。502 错误应先检查后端监听、FPM 服务与 socket 权限;页面可开但资源 404,先核对 APP_URL 和 proxy_pass 的尾斜线。

还应从外部网络确认内部 8080 端口不可直接访问;针对自己控制的部署,检查 /bookstack/.env 及应用私有路径不会返回真实文件内容。只收到一个 404 状态并不足以证明全部权限都正确,需结合响应体、访问日志及其他虚拟主机的根目录核对。源文安装流程可能带有初始管理员账户,必须按所用安装方式完成凭据初始化;不要保留公开默认密码。

这篇配置解决了什么

完成这组规则后,子路径只是访问入口,BookStack 的应用目录仍然独立,只有 public 对外提供内容。全文所示命令具有修改服务的副作用,必须在自己的可回退环境中操作。静态审核确认没有写入真实凭据;也指出了公开监听、旧 PHP 路径和代理信任的实际问题。但本文没有运行 Nginx、Apache 或 PHP,不能据此宣称部署已经通过安全测试。


来源与署名:BookStack 官方文档,项目由 Dan Brown 与社区开发,网站版权 © 2015–2026 Dan Brown。主要来源:Subdirectory Setup;补充:Installation、Security。技术修订及示意图:未完纪。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容