一、安装nextcloud的配置:

  1. 首先创建一个新网络,用于桥接caddy和nextcloud。

    docker network create proxy-net
  2. caddy的docker-compose.yml:

    services:
      caddy:
     image: caddy:latest
     container_name: caddy
     restart: always
     ports:
       - "80:80"
       - "443:443"
       - "443:443/udp" # 支持 HTTP/3
     networks:
       - proxy-net
       - nextcloud-aio
     volumes:
       - ./Caddyfile:/etc/caddy/Caddyfile
       - caddy_data:/data
       - caddy_config:/config
    networks:
      proxy-net:
     external: true
      nextcloud-aio:
     external: true
     name: nextcloud-aio
    volumes:
      caddy_data:
      caddy_config:
  3. Caddyfile:
#全局配置块必须在最前面
{
    # 全局日志输出标准化 JSON,供 Fail2Ban 读取
    log {
        output file /var/log/caddy/access.log {
            roll_size 50mb
            roll_keep 5
            roll_keep_for 30d  # 建议加上这个:保留不超过30天,防止占用过多磁盘
        }
        format json
    }
}

# 2. 定义你的代码片段 (Snippet)
(common_security) {
    header {
        # 强制 HTTPS 
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        
        # 防止 MIME 类型嗅探
        X-Content-Type-Options "nosniff"
        
        # 隐藏 Server 软件信息
        -Server
        
        # 【新增】防止点击劫持 (Clickjacking)
        # 禁止你的网页被别人以 <iframe> 的形式嵌入到他们的网站中
        X-Frame-Options "SAMEORIGIN"
        
        # 【新增】跨站脚本防护 (XSS)
        # 遇到跨站脚本攻击时强制浏览器拦截渲染
        X-XSS-Protection "1; mode=block"
        
        # 【新增】控制 Referrer 信息泄露
        # 当从 HTTPS 降级访问 HTTP 时不发送来源信息,平时跨域只发送域名
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}

your-nextcloud-aio.domain {
    encode gzip
    reverse_proxy nextcloud-aio-apache:11000 {
        header_up X-Forwarded-For {http.request.header.X-Forwarded-For},{remote_host}
        header_up Host {host}
        header_up X-Real-IP {remote_host}
    }
}

注:Nextcloud AIO 内部其实自带了一部分安全 Header,但在总网关层再覆盖/加强一次是标准的纵深防御最佳实践。

二、因为nextcloud不适合通过cloudflare代理访问(文件大小,其他跨站问题等),而这个主机延迟又较高,所以给它加上一个优化机入口。

优化机的Caddyfile:

services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: always
    network_mode: host      
    # 直接使用宿主机网络;性能最好;安全取决于防火墙;
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
      - ./certs:/etc/caddy/certs
volumes:
  caddy_data:
  caddy_config:

💡 如果你必须使用docker网桥(v6桥接),那么需要下面的配置,并确保宿主机的内核开启了 IPv6 转发功能

sysctl -w net.ipv6.conf.all.forwarding=1
#需要固化到systctl.d设置里
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    networks:
      - proxy-net
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
      - ./certs:/etc/caddy/certs

networks:
  proxy-net:
    enable_ipv6: true
    ipam:
      config:
        - subnet: fd00:d63a:61:2::/64 
# 这是底层网络引擎分配 IP 所必须的,不能省;查看/etc/docker/daemon.json获得。

volumes:
  caddy_data:
  caddy_config:

三、同步nextcloud主机上的caddy下面的certs目录到反代机

反代机的Caddyfile

your-nextcloud.com {
        tls /etc/caddy/certs/your-nextcloud.com/your-nextcloud.com.crt /etc/caddy/certs/your-nextcloud.com/your-nextcloud.com.key
    # 2. 反向代理到家中的 IPv6
    reverse_proxy [2a02---v6地址]:443 {
        header_up Host your-nextcloud.com
        transport http {
            # 开启后端 TLS 验证
            tls
            # 关键:告诉外部 Caddy 握手时发送这个域名
            # 否则外部 Caddy 可能会因为无法验证“自签/私有”证书而拒绝连接
            tls_server_name your-nextcloud.com
            # 如果证书链不完整导致 502,临时开启下面这行测试
            #tls_insecure_skip_verify
        }
    }
}

四. 修改

// 1. 确保信任列表覆盖了你的所有本地容器网段和外部 IPv6
  'trusted_proxies' => 
  array (
    0 => '127.0.0.1',
    1 => '::1',
    2 => '172.18.0.0/16',           // 请确认这是你 AIO 所在的 docker 网络段
    3 => '172.19.0.0/16',           // 如果本地 Caddy 在另一个 docker 网络,也加上
    4 => '240e:xxxx:xxxx:xxxx::/64', // 【必须】外部 Caddy 的公网 IP(v4和v6都填上)
  ),

  // 2. 告诉 Nextcloud 必须去读取哪个头部来获取真实 IP
  'forwarded_for_headers' => 
  array (
    0 => 'HTTP_X_FORWARDED_FOR',
  ),

  // 3. 覆盖协议和主机名(确保前端显示正常,避免死循环)
  'overwritehost' => 'your-nxcloud-domain.com',
  'overwriteprotocol' => 'https',
  'overwritecondaddr' => '^.*$',   // 允许任何 IP 触发覆盖规则


  'forwarded_for_headers' => 
  array (
    0 => 'HTTP_X_FORWARDED_FOR',
  ),
  'overwritehost' => 'de.imzen.de',
  'overwriteprotocol' => 'https',
  'overwritecondaddr' => '^.*$',

完成。

💡 顺便也解决了仅v4的线路访问ipv6服务的问题。(反代机是双栈)

可以检查下nextcloud的安全设置里,是否显示了你的真实IP,而不是127.0.0.1或127.0.18.1这样的docker内网地址。上面的设置已经正确的设置了header。caddy日志和nextcloud应该显示真实的IP来源。