日常Web运维

在Caddy下配置nextcloud伪静态

nextcloud是一个用php实现的网盘程序,其中路径路由的部分只能交给前端Web服务器的rewrite来进行。在Apache2,它提供了.htaccess文件支持自动配置,在nginx上也有标准的配置。

Caddy真的是个不错的服务器程序,目前支持TLS1.3和QUIC,它官方提供的nextcloud配置文件是可以使用的,但是使用时,每每看到那个index.php,那是一个丑+难受啊。因而,经过尝试,把伪静态配置实现了,并且分享出来。

基本配置

这里把基本的配置写出来了,不想看下去的可以抄了然后按Ctrl+w或者Cmd+w了。

example.com {
    root /var/www/html
    # tls
    tls yourmail@example.com {
        # key_type p256
    }

    # php
    fastcgi / phpfpm:9000 php {
        env PATH /bin
        env front_controller_active true
        env modHeadersAvailable true
    }

    header / {
        # HSTS
        # Strict-Transport-Security "max-age=15768000;"
        # anti XSS
        X-Content-Type-Options "nosniff"
        X-XSS-Protection "1; mode=block"
        X-Permitted-Cross-Domain-Policies "none"
        # robots tag
        X-Robots-Tag "none"
        # download options
        X-Download-Options "noopen"
        # referer policy
        Referrer-Policy "no-referrer"
        # remove php version, which is sensitive
        -X-Powered-By
    }

    # client support (e.g. os x calendar / contacts)
    redir /.well-known/carddav /remote.php/carddav 301
    redir /.well-known/caldav /remote.php/caldav 301

    # functional rewrite
    rewrite {
        r ^/\.well-known/host-meta$
        to /public.php?service=host-meta&{query}
    }
    rewrite {
        r ^/\.well-known/host-meta\.json$
        to /public.php?service=host-meta-json&{query}
    }
    rewrite {
        r ^/\.well-known/webfinger$
        to /public.php?service=webfinger&{query}
    }

    # checks for images and css js
    rewrite {
        ext .js .svg .gif .png .html .ttf .woff .ico .jpg .jpeg .css
        r ^/(.+)$
        to /{1} /index.php?{1}
    }

    # for direct php using case
    rewrite {
        if_op or
        if {path} starts_with /updater
        if {path} starts_with /ocm-provider
        if {path} starts_with /ocs-provider
        r /.*
        to {path}/
    }

    # route the views to index.php
    rewrite {
        ext /
        if_op and
        if {path} not_starts_with /index.php
        if {path} not_starts_with /remote.php
        if {path} not_starts_with /public.php
        if {path} not_starts_with /corn.php
        if {path} not_starts_with /core/ajax/update.php
        if {path} not_starts_with /status.php
        if {path} not_starts_with /updater
        if {path} not_starts_with /ocs
        if {path} not_starts_with /.well-known/
        r /(.*)
        to /index.php?{query}
    }

    # remove trailing / as it causes errors with php-fpm
    rewrite {
        r ^/remote.php/(webdav|caldav|carddav|dav)(\/?)(\/?)$
        to /remote.php/{1}
    }
    rewrite {
        r ^/remote.php/(webdav|caldav|carddav|dav)/(.+?)(\/?)(\/?)$
        to /remote.php/{1}/{2}
    }
    rewrite {
        r ^/public.php/(dav|webdav|caldav|carddav)(\/?)(\/?)$
        to /public.php/{1}
    }
    rewrite {
        r ^/public.php/(dav|webdav|caldav|carddav)/(.+)(\/?)(\/?)$
        to /public.php/{1}/{2}
    }

    # should not be accessible from outside
    status 403 {
        /.htaccess
        /data
        /config
        /db_structure
        /.xml
        /README
    }
}

变更解读

这份配置文件与官方的相比,变更的内容有以下几点:

  • fastcgi参数变化
  • 将安全性的header放在Caddy部分完成,去除X-Powered-By字段
  • 匹配URL表达式由^/index.php/.*变为了^/.*
  • 增加了不经index.php使用目录的case

伪静态开启

伪静态有两步,一个在于Caddy这边对于伪静态路径的重写,另一个在于nextcloud本身开启pretty URL。官方并没有具体表示这个pretty URL怎么用,但是经过翻找,我这边找到了一个fastcgi的参数:

env front_controller_active true

这里就会传递给nextcloud,然后它生成的网页返回的就没有那个难看的index.php了。

然后,我们把需要用到的场景重写到index.php上,这样就可以做到伪静态了。

# route the views to index.php
rewrite {
    ext /
    if_op and
    if {path} not_starts_with /index.php
    if {path} not_starts_with /remote.php
    if {path} not_starts_with /public.php
    if {path} not_starts_with /corn.php
    if {path} not_starts_with /core/ajax/update.php
    if {path} not_starts_with /status.php
    if {path} not_starts_with /updater
    if {path} not_starts_with /ocs
    if {path} not_starts_with /.well-known/
    r /(.*)
    to /index.php?{query}
}

同时面对一些使用目录下的index.php的情况做了豁免处理。

# for direct php using case
rewrite {
    if_op or
    if {path} starts_with /updater
    if {path} starts_with /ocm-provider
    if {path} starts_with /ocs-provider
    r /.*
    to {path}/
}

header处理

这里的header就会交回给Caddy处理,如下:

header / {
    # HSTS
    # Strict-Transport-Security "max-age=15768000;"
    # anti XSS
    X-Content-Type-Options "nosniff"
    X-XSS-Protection "1; mode=block"
    X-Permitted-Cross-Domain-Policies "none"
    # robots tag
    X-Robots-Tag "none"
    # download options
    X-Download-Options "noopen"
    # referer policy
    Referrer-Policy "no-referrer"
    # remove php version, which is sensitive
    -X-Powered-By
}

为了防止php程序一侧又自己加了header,需要传一个参数进去,来告诉它http服务器已经处理了这个问题。、

env modHeadersAvailable true

References

  1. Nextcloud pretty URLs not working (rewrite)
  2. Pretty links not working

发表评论

电子邮件地址不会被公开。 必填项已用*标注