前言
尝试了多种 Nextcloud AIO(All In One)私有云服务部署方式,并记录了过程中遇到的问题和解决方案。
这里主要介绍三种方案:
- 方案1:流量全走公网服务器,使用Frp进行内网穿透。
- 方案2:目前最权威(官方推荐的)的Tailscale代理整合方案,不需要公网服务器。虽然看起来方便,然而存在多一层NAT的明显缺陷,并且有很多坑(主要是Docker内DNS的问题)。
- 方案3(推荐):使用内网宿主机Tailscale代理,并使用公网服务器DERP中继。在内网或NAT类型较好的网络环境下可以直连,网络环境差时流量才走公网服务器。
方案1:Frp内网穿透(Nextcloud AIO + Frp + nginx-proxy-manager)
网络拓扑
假设已有域名为nextcloud.yourhost.com
自有域名:443 → 公网服务器 [ 443:Nginx:10080 → 10080:frps:7000 ] → 内网服务器 [ 随机端口:frpc:11000 → Docker [ 11000:Nextcloud AIO ] ]
其中Nginx和frps安装在具有公网IP的服务器上,frpc和Nextcloud安装在内网服务器中。使用网络桥接的docker会被特别标出。
Nginx配置
通过docker安装nginx-proxy-manager
公网服务器中,新建个文件夹,创建docker-compose.yml文件
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports: # 或者直接 network_mode: host
- '80:80' # http端口
- '81:81' # 管理界面端口
- '443:443' # https端口
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
docker compose up -d启动后访问81端口打开nginx-proxy-manager管理界面(防火墙记得打开80, 81, 443)
nginx-proxy-manager配置
按下述文档配置nginx-proxy-manager
https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#nginx-proxy-manager—npm
其中Domain Names填入nextcloud.yourhost.com
由于我使用docker安装nginx-proxy-manager,Forward IP应当填docker中的宿主机IP:127.17.0.1(通过ip addr show docker0查找得到)
Forward Port改为 Frps 的vhostHTTPPort,如10080,与下面一致
Frps配置
下载Frp,到公网服务器中,我下载到/opt/frp/,请根据实际情况修改路径。
配置Frps
/opt/frp//frps.toml
bindPort = 7000
auth.token = xxxxx
vhostHTTPPort = 10080
vhostHTTPSPort = 10443
bindPort 为frp服务器和客户端通信端口,记得打开防火墙。
auth.token 可设置为一个随机字符串,用于通信加密。
vhostHTTPPort和vhostHTTPSPort为http/https服务监听端口,用于给本机的nginx访问。
配置Frps开机启动
/etc/systemd/system/frps.service
[Unit]
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
ExecStart = /opt/frp/frps -c /opt/frp/frps.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy = multi-user.target
执行
sudo systemctl enable frps
sudo systemctl start frps
Frpc配置
配置Frpc
下载Frp,到内网服务器中,我下载到/opt/frp/,请根据实际情况修改路径。
/opt/frp/frpc.toml
serverAddr = "yourhost.com"
serverPort = 7000
auth.token = xxxxx
includes = ["./confd/*.toml"]
bindPort 和 auth.token 需要与Frps一致,其他根据实际填写。
/opt/frp/confd/nextcloud.toml
[[proxies]]
name = "nextcloud"
type = "http"
localIP = "127.0.0.1"
localPort = 11000
customDomains = ["nextcloud.yourhost.com"]
配置通过nextcloud.yourhost.com访问公网服务器转发到内网服务器的127.0.0.1:11000,内网—公网服务器之间以及Frpc—NextCloud之间使用http通信。
这里的localPort 要与下面的APACHE_PORT对应
配置Frpc开机启动
/etc/systemd/system/frpc.service
[Unit]
Description = frp client
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
WorkingDirectory=/opt/frp
ExecStart = /opt/frp/frpc -c /opt/frp/frpc.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy = multi-user.target
执行
sudo systemctl enable frps
sudo systemctl start frps
Nextcloud AIO配置
内网服务器中新建个文件夹,创建docker-compose.yml文件:
version: '3.8'
services:
nextcloud-aio-mastercontainer:
image: ghcr.io/nextcloud-releases/all-in-one:latest
container_name: nextcloud-aio-mastercontainer
restart: always
ports:
- "18080:8080"
volumes:
- aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- APACHE_PORT=11000
- APACHE_IP_BINDING=0.0.0.0
- SKIP_DOMAIN_VALIDATION=false
- NEXTCLOUD_DATADIR=/newdata/nextcloud
- NEXTCLOUD_UPLOAD_LIMIT=128G
- NEXTCLOUD_MAX_TIME=36000
- NEXTCLOUD_MEMORY_LIMIT=1024M
- NEXTCLOUD_ENABLE_DRI_DEVICE=true
init: true
sysctls:
- net.core.somaxconn=1024
deploy:
restart_policy:
condition: any
volumes:
aio_mastercontainer:
NEXTCLOUD_DATADIR设置为你的数据储存路径
启动 docker:
docker compose up -d
随后打开localhost:18080执行初始化流程即可完成安装。
常见问题
Imagick插件无法下载
初始化过程中,容器nextcloud-aio-nextcloud可能会卡在Enabling Imagick...
2025-07-04T15:09:58.253331095Z Connection to nextcloud-aio-database (172.20.0.5) 5432 port [tcp/postgresql] succeeded!
2025-07-04T15:09:58.253810507Z + '[' -f /dev-dri-group-was-added ']'
2025-07-04T15:09:58.254285584Z ++ find /dev -maxdepth 1 -mindepth 1 -name dri
2025-07-04T15:09:58.255071763Z + '[' -n /dev/dri ']'
2025-07-04T15:09:58.255453279Z ++ find /dev/dri -maxdepth 1 -mindepth 1 -name renderD128
2025-07-04T15:09:58.256215830Z + '[' -n /dev/dri/renderD128 ']'
2025-07-04T15:09:58.256741487Z ++ stat -c %g /dev/dri/renderD128
2025-07-04T15:09:58.258725601Z + GID=993
2025-07-04T15:09:58.258744684Z + groupadd -g 993 render2
2025-07-04T15:09:58.270615549Z ++ getent group 993
2025-07-04T15:09:58.270649267Z ++ cut -d: -f1
2025-07-04T15:09:58.272696310Z + GROUP=render2
2025-07-04T15:09:58.272728341Z + usermod -aG render2 www-data
2025-07-04T15:09:58.288824588Z + touch /dev-dri-group-was-added
2025-07-04T15:09:58.291171246Z + set +x
2025-07-04T15:09:58.305853077Z Enabling Imagick...
这主要是网络问题,建议等几个小时,如果还是不行,执行下述操作禁用Imagick插件(不推荐)或者使用宿主机代理(推荐)。
禁用 Imagick 插件
在docker-compose.yml的environment:项中添加一行,将PHP插件列表设为空
- NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=
保存后,执行清理,然后重新运行docker compose up -d
使用宿主机代理
该脚本能够使nextcloud-aio-nextcloud容器初始化过程使用宿主机代理,卡Enabling Imagick...时直接执行该脚本即可。
attach_proxy.sh
#!/bin/bash
CONTAINER_NAME="nextcloud-aio-nextcloud"
START_SH_PATH="/start.sh"
BACKUP_PATH="/start.sh.bak"
# 要插入的内容
PROXY_EXPORTS='export HTTP_PROXY=http://172.17.0.1:10809
export HTTPS_PROXY=http://172.17.0.1:10809
export ALL_PROXY=socks5://172.17.0.1:10808
export NO_PROXY=localhost,127.0.0.1,::1,*.local,169.254.169.254,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8,100.0.0.0/24'
echo "🔍 正在修改容器 $CONTAINER_NAME 的 $START_SH_PATH 文件..."
# Step 1: 备份原始 start.sh
docker exec "$CONTAINER_NAME" cp "$START_SH_PATH" "$BACKUP_PATH"
# Step 2: 插入环境变量到第2行(保持 shebang 不变)
docker exec "$CONTAINER_NAME" /bin/sh -c "
head -n 1 $START_SH_PATH > /tmp/start.sh && \
echo \"$PROXY_EXPORTS\" >> /tmp/start.sh && \
tail -n +2 $START_SH_PATH >> /tmp/start.sh && \
mv /tmp/start.sh $START_SH_PATH && \
chmod +x $START_SH_PATH
"
# Step 3: 重启容器
echo "🔁 重启容器 $CONTAINER_NAME..."
docker restart "$CONTAINER_NAME"
echo "✅ 修改完成并重启成功。"
其中172.17.0.1为容器中的宿主机IP,10808和10809修改为宿主机网络代理的端口。
清理安装环境
当需要还原到安装前状态时,执行清理:
docker compose down --volumes
docker rm -f $(docker ps -aq --filter name=^nextcloud-aio --filter name=^nextcloud_aio)
docker volume rm $(docker volume list -q --filter name=^nextcloud-aio --filter name=^nextcloud_aio)
docker network remove nextcloud-aio
# sudo rm -r /newdata/nextcloud # 路径与上面NEXTCLOUD_DATADIR一致。执行该项会删除NextCloud中的所有用户文件
方案2:内网Tailscale多合一(Nextcloud AIO + Tailscale + Caddy)
- 该方案缺陷明显,已弃用。
由于方案1流量必需过公网服务器,难以按需通过多种方式连接NextCloud服务,如在可用时流量走局域网。
因此,后续尝试了基于 Tailscale 的方案。该方案要求访问Nextcloud的终端安装了Tailscale并加入了同一个Tailscale局域网,Tailscale会根据网络环境自动路由流量,适合内网环境使用。
网络拓扑
假设你的Tailscale域名为nextcloud.xxxx.ts.net,SSL证书将由Caddy处理。
Tailscale域名:443 → 内网服务器 [ Docker [ Tailscale → 443:Caddy:11000 → 11000:Nextcloud AIO ] ]
配置方案
具体参考:https://github.com/nextcloud/all-in-one/discussions/5439
该方案用一份Docker配置管理Nextcloud AIO + Tailscale + Caddy,属于是AIO外又一个AIO。
其中compose.yml配置如下
services:
nextcloud-aio-mastercontainer:
image: ghcr.io/nextcloud-releases/all-in-one:latest
init: true
restart: always
container_name: nextcloud-aio-mastercontainer # This line cannot be changed.
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- nextcloud-aio
ports:
- 0.0.0.0:18080:8080
environment:
APACHE_PORT: 11000
APACHE_IP_BINDING: 127.0.0.1
SKIP_DOMAIN_VALIDATION: "true"
NEXTCLOUD_DATADIR: /newdata/nextcloud
NEXTCLOUD_UPLOAD_LIMIT: 128G
NEXTCLOUD_MAX_TIME: 36000
NEXTCLOUD_MEMORY_LIMIT: 1024M
NEXTCLOUD_ENABLE_DRI_DEVICE: "true"
caddy:
build:
context: .
dockerfile: Caddy.Dockerfile
depends_on:
tailscale:
condition: service_healthy
restart: unless-stopped
environment:
NC_DOMAIN: nextcloud.tailb1a5cf.ts.net # Change this to your domain ending with .ts.net in the format {$TS_HOSTNAME}.{tailnetdomain}
volumes:
- type: bind
source: ./Caddyfile
target: /etc/caddy/Caddyfile
- type: volume
source: caddy_certs
target: /certs
- type: volume
source: caddy_data
target: /data
- type: volume
source: caddy_config
target: /config
- type: volume
source: tailscale_sock
target: /var/run/tailscale/ # Mount the volume for /var/run/tailscale/tailscale.sock
read_only: true
network_mode: service:tailscale
tailscale:
image: tailscale/tailscale:v1.82.0
environment:
TS_HOSTNAME: nextcloud # Enter the hostname for your tailnet
TS_AUTH_KEY: tskey-auth-XXXXXXXXXXXX-XXXXXXXXXXXXXX # OAuth client key recommended
TS_EXTRA_ARGS: --advertise-tags=tag:nextcloud
TS_AUTH_ONCE: true
init: true
healthcheck:
test: tailscale status --peers=false --json | grep 'Online.*true'
start_period: 3s
interval: 1s
retries: 3
restart: unless-stopped
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- type: volume
source: tailscale
target: /var/lib/tailscale
- type: volume
source: tailscale_sock
target: /tmp # Mounting the entire /tmp folder to access tailscale.sock
cap_add:
- NET_ADMIN
networks:
- nextcloud-aio
volumes:
nextcloud_aio_mastercontainer:
name: nextcloud_aio_mastercontainer # This line cannot be changed.
caddy_certs:
caddy_config:
caddy_data:
tailscale:
tailscale_sock:
networks:
nextcloud-aio:
name: nextcloud-aio
driver: bridge
enable_ipv6: false
driver_opts:
com.docker.network.driver.mtu: "1280" # You can set this to 9001 etc. to use jumbo frames, but packets may be dropped.
com.docker.network.bridge.host_binding_ipv4: "127.0.0.1" # Harden aio
com.docker.network.bridge.enable_icc: "true"
com.docker.network.bridge.default_bridge: "false"
com.docker.network.bridge.enable_ip_masquerade: "true"
注意事项
- 需要打开tailscale的HTTPS Certificates
- 获取ts密钥时记得勾选
Ephemeral - 手动迁移/修改数据后输入
docker exec -it nextcloud-aio-nextcloud su www-data -c "php /var/www/html/occ files:scan --all"扫描更新 - NextCloud 的 docker volume 存放位置无法更改,手动迁移 docker volume 时需要使用
cp -rp保留文件权限标识 - 若出现 Nextcloud Office (Collabora) 和 Nextcloud Talk 无法使用,其中 Nextcloud Office 报错
未经授权的WOPI主机或Unauthorized WOPI host,并且在nextcloud-aio-collabora容器log中出现ERR: could not resolve host ...字样,说明子容器无法解析tailscale域名。需要在宿主机安装Tailscale,并将DNS加入docker容器中,具体操作如下:
sudo vim /etc/docker/daemon.json
# 写入
{
"dns": ["100.100.100.100", "8.8.8.8", "114.114.114.114"],
}
# 执行
sudo systemctl restart docker
方案3(推荐):内网Tailscale + 可选公网中继(Nextcloud AIO + Tailscale + nginx-proxy-manager)
上述基于Tailscale的方法由于Tailscale使用容器部署,并且藏在Docker Network中,多了一层NAT,导致NAT类型较差,常常宿主机Tailscale打洞成功而容器内的Tailscale打洞失败。而且使用Tailscale域名不灵活,在需要切换网络拓扑时修改域名十分复杂。
因此最后采用了 自有域名 + 宿主机Tailscale + Nginx + DERP中继 的方案。
- 该方案的DERP中继是可选的,即使不使用DERP中继,由于Tailscale少一层NAT,该方案的网络连通性也比方案2更好。
网络拓扑
假设已有域名为nextcloud.yourhost.com
自有域名:443 → 解析为Tailscale局域网IP → ( 公网服务器 [ Tailscale DERP 中继 ] → ) 内网服务器 [ Tailscale → 443:nginx-proxy-manager:11000 → Docker [ 11000:Nextcloud AIO ] ]
该方案与方案1兼容,可以通过修改域名解析调整网络拓扑的前半部分,在使用Tailscale和使用Frp之间切换,当然更建议直接使用Tailscale + 自建DERP中继。
域名解析
在内网服务器中安装Tailscale,将域名nextcloud.yourhost.com解析为内网服务器的Tailscale IP,我设置的是100.100.1.1。
Nginx配置
使用 Docker 运行 nginx-proxy-manager
docker-compose.yml
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
network_mode: host
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
执行以下命令启动 nginx-proxy-manager,并通过81端口访问web管理界面
docker compose up -d
SSL证书
如果已有SSL证书,不需要使用nginx-proxy-manager的自动SSL功能,请自行导入证书并跳过这一节。
通常 nginx-proxy-manager 会自动申请对应域名的SSL证书,但必需有公网IP解析才能使用,与上述网络拓扑相悖。因此,在获取SSL证书时必需修改网络拓扑,通过类似:
域名解析 → 公网服务器IP → 公网服务器 [ frps ] → 内网服务器 [ frpc → nginx-proxy-manager ]
这样网络拓扑,使得内网nginx-proxy-manager能够被通过域名访问,以使用nginx-proxy-manager的自动SSL功能获取证书。获取证书成功后,将解析换回 Tailscale 的局域网IP。
nginx-proxy-manager配置
按下述文档配置nginx-proxy-manager
https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#nginx-proxy-manager—npm
其中Domain Names填入nextcloud.yourhost.com,Forward IP应当填:127.0.0.1(填localhost不行,经测试会502),Forward Port填11000。
Nextcloud AIO 配置
没什么好说的,配置文件如下,细节见方案1的常见问题。
services:
nextcloud-aio-mastercontainer:
image: ghcr.io/nextcloud-releases/all-in-one:latest
init: true
restart: always
container_name: nextcloud-aio-mastercontainer # This line cannot be changed.
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- 0.0.0.0:18080:8080
environment:
APACHE_PORT: 11000
APACHE_IP_BINDING: 0.0.0.0
SKIP_DOMAIN_VALIDATION: "true"
NEXTCLOUD_DATADIR: /newdata/nextcloud
NEXTCLOUD_UPLOAD_LIMIT: 128G
NEXTCLOUD_MAX_TIME: 36000
NEXTCLOUD_MEMORY_LIMIT: 8192M
NEXTCLOUD_ENABLE_DRI_DEVICE: "true"
volumes:
nextcloud_aio_mastercontainer:
name: nextcloud_aio_mastercontainer # This line cannot be changed.
自建 Tailscale DERP 中继(可选)
通过在具有公网IP的公网服务器中安装Tailscale并登录,随后搭建Tailscale DERP 中继,可以使得在网络条件较差时使用该服务器进行数据中继,以确保Nextcloud的可访问性。
获取 DERP SSL 证书
Tailscale DERP需要专用域名,设置derp.yourhost.com解析到公网服务器IP,使用 nginx-proxy-manager 获取derp.yourhost.com的SSL证书,该证书会储存在容器中的/etc/letsencrypt/live/npm-x/文件夹里,根据容器/etc/letsencrypt映射的路径找到你宿主机对应的文件夹,我这里是/home/yourname/nginx/letsencrypt/live/npm-4/。
开启 DERP 服务
运行以下命令开启 Tailscale DERP 中继服务:
docker run -dit \
--name derper \
--restart always \
--volume /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \
--volume /home/yourname/nginx/letsencrypt/live/npm-4/fullchain.pem:/app/certs/derp.yourhost.com.crt \
--volume /home/yourname/nginx/letsencrypt/live/npm-4/privkey.pem:/app/certs/derp.yourhost.com.key \
-e DERP_CERT_MODE=manual \
-e DERP_ADDR=:13387 \
-e DERP_HTTP_PORT=-1 \
-e DERP_STUN_PORT=13388 \
-e DERP_DOMAIN=derp.yourhost.com \
-e DERP_VERIFY_CLIENTS=true \
-p 13387:13387 \
-p 13388:13388/udp \
fredliang/derper
注意修改本地证书路径以及三处derp.yourhost.com,并开放防火墙对应端口。
设置Tailscale DERP节点
在Tailscale网页控制面板的Access controls中编辑配置文件,修改其中的 derpMap 部分设置:
{
"derpMap": {
// "OmitDefaultRegions": false,
"OmitDefaultRegions": true,
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "MyDerpRegion",
"RegionName": "YourRegionName",
"Nodes": [
{
"Name": "MyDerpNode",
"RegionID": 900,
"HostName": "derp.yourhost.com",
"DERPPort": 13387,
"STUNPort": 13388,
"STUNOnly": false,
},
],
},
},
},
}
保存后在任意连接了该Tailscale网络的终端输入tailscale netcheck检查是否成功设置DERP服务:
> tailscale netcheck
Report:
* Time: 2025-07-15T07:48:08.465723Z
* UDP: true
* IPv4: yes, XXX.XXX.XXX.XXX:XXXX
* IPv6: no, but OS has support
* MappingVariesByDestIP:
* PortMapping:
* Nearest DERP: YourRegionName
* DERP latency:
- MyDerpRegion: 56.8ms (YourRegionName)
常见问题
- 域名解析修改为局域网地址时,部分DNS服务器缓存更新会较慢,建议使用8.8.8.8之类的DNS服务
- Nextcloud AIO 修改域名参见https://github.com/nextcloud/all-in-one#how-to-change-the-domain

1816





