網絡拓撲
假設已有域名為nextcloud.yourhost.com
用戶通過域名https訪問 -> Nginx -> frps -> frpc -> NextCloud
其中Nginx和frps安裝在具有公網IP的服務器上,frpc和NextCloud安裝在內網服務器中。
Nginx配置
通過docker安裝nginx-proxy-manager
外網服務器中,新建個文件夾,創建docker-compose.yml文件
version: '3'
services:app:image: 'jc21/nginx-proxy-manager:latest'container_name: nginx-proxy-managerrestart: unless-stoppedports:- '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 = 37870
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 = 37870
auth.token = xxxxxincludes = ["./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:latestcontainer_name: nextcloud-aio-mastercontainerrestart: alwaysports:- "18080:8080"volumes:- aio_mastercontainer:/mnt/docker-aio-config- /var/run/docker.sock:/var/run/docker.sock:roenvironment:- 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=trueinit: truesysctls:- net.core.somaxconn=1024deploy:restart_policy:condition: anyvolumes: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
清理安裝環境
當需要還原到安裝前狀態時,執行清理:
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中的所有用戶文件
后記
由于NextCloud必需使用固定域名+SSL,因此使用該方案并不靈活,難以通過多種方式連接NextCloud服務,如在可用時流量走局域網。因此,最后采用了基于Tailscale 的方案。
其中compose.yml配置如下
services:nextcloud-aio-mastercontainer:image: ghcr.io/nextcloud-releases/all-in-one:latestinit: truerestart: alwayscontainer_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:ronetworks:- nextcloud-aioports:- 0.0.0.0:18080:8080environment:APACHE_PORT: 11000APACHE_IP_BINDING: 127.0.0.1SKIP_DOMAIN_VALIDATION: "true"NEXTCLOUD_DATADIR: /newdata/nextcloudNEXTCLOUD_UPLOAD_LIMIT: 128GNEXTCLOUD_MAX_TIME: 36000NEXTCLOUD_MEMORY_LIMIT: 1024MNEXTCLOUD_ENABLE_DRI_DEVICE: "true"caddy:build:context: .dockerfile: Caddy.Dockerfiledepends_on:tailscale:condition: service_healthyrestart: unless-stoppedenvironment:NC_DOMAIN: nextcloud.tailb1a5cf.ts.net # Change this to your domain ending with .ts.net in the format {$TS_HOSTNAME}.{tailnetdomain}volumes:- type: bindsource: ./Caddyfiletarget: /etc/caddy/Caddyfile- type: volumesource: caddy_certstarget: /certs- type: volumesource: caddy_datatarget: /data- type: volumesource: caddy_configtarget: /config- type: volumesource: tailscale_socktarget: /var/run/tailscale/ # Mount the volume for /var/run/tailscale/tailscale.sockread_only: truenetwork_mode: service:tailscaletailscale:image: tailscale/tailscale:v1.82.0environment:TS_HOSTNAME: nextcloud # Enter the hostname for your tailnetTS_AUTH_KEY: tskey-auth-XXXXXXXXXXXX-XXXXXXXXXXXXXX # OAuth client key recommendedTS_EXTRA_ARGS: --advertise-tags=tag:nextcloudinit: truehealthcheck:test: tailscale status --peers=false --json | grep 'Online.*true'start_period: 3sinterval: 1sretries: 3restart: unless-stoppeddevices:- /dev/net/tun:/dev/net/tunvolumes:- type: volumesource: tailscaletarget: /var/lib/tailscale- type: volumesource: tailscale_socktarget: /tmp # Mounting the entire /tmp folder to access tailscale.sockcap_add:- NET_ADMINnetworks:- 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-aiodriver: bridgeenable_ipv6: falsedriver_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 aiocom.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