Slef-Hosted:Nextcloud 部署

Nextcloud 的部署方式有很多种,经过折腾,发现了一种比较好的部署方式,我称之为混合部署。

在 QNAP 威联通 QTS 里部署 Nextcloud 的方式一般有以下几种:

  • 常规的 LAMP 部署
  • 通过 CLI 脚本部署
  • QNAP qpkg 文件部署
  • 通过 all-in-one Docker 部署
  • 使用 QNAP 自带 Apache 部署

我使用过 3 种部署方式,

  • 系统自带 Apache + Nextcloud 源码
  • all-in-one Docker 部署
  • 混合部署:公共 php-fpm + Nextcloud 源码

前两个我就简单介绍下,不做过多展开。

第三个会详细介绍一下。

以下环境均为 QNAP 威联通的 NAS 系统。其他系统路径可能需要自行调整。

系统自带的 Apache 部署

之前我一直用 QNAP 自带的 Apache 来安装 Nextcloud,通过 域名+Nextcloud端口号 的方式来访问。

但是后来随着服务越来越多,我使用 Nginx Proxy Manager 来统一进行反代,使用 二级域名+固定端口 的方式来访问各种服务,比较快捷方便。这时在配置 Apache + Nextcloud 反代时,搞了半天也没搞好。

另外系统自带的 Apache 版本较低,无法安装最新的 Nextcloud。而 Nextcloud 的大版本更新,还往往伴随着 break change,我有些担心一直不升级落后太多,等到想升级时会很麻烦或者造成一些数据损坏。

优点:效率高
缺点:

  • 配置比较麻烦(如果不用 Nginx 进行反代的话倒是简单,但是那样访问起来不够”优雅”)
  • 自带的 php 版本较低,Nextcloud 高版本对 php 版本有要求

All-in-ONE Docker 部署

很多人非常喜欢用官方 all-in-one docker 的安装方式,感觉轻松快捷,但是这个 all-in-one docker 我感觉开销是大了些


优点:部署简单,官方 docker 已经打包好了
缺点:如图中所示,链路较长,效率较低

对应的 docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
version: "2"
services:
nextcloud:
image: linuxserver/nextcloud:latest
container_name: nextcloud
environment:
#- MYSQL_PASSWORD=password
#- MYSQL_DATABASE=nextcloud
#- MYSQL_USER=oc_admin
#- MYSQL_HOST=127.0.0.1:3306
- TZ=Asia/Shanghai
volumes:
- /my_home/nextcloud/config:/config:rw
- /my_home/nextcloud/data:/data:rw
ports:
- 2080:80
restart: always

混合部署:公用 php-fpm + Nextcloud

我目前在用的方式,已经稳定运行了半年了,更新起来毫无压力,管理界面上的检查也能全部 pass。

优点:效率高,php 版本、库包都在自己掌控中
缺点:php 需要自己编译镜像

相关配置如下:

编译 php-fpm 镜像的 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
FROM php:8-fpm

RUN pecl install apcu && docker-php-ext-enable apcu

RUN CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" LDFLAGS="$PHP_LDFLAGS" \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
libmagickwand-dev \
&& rm -rf /var/lib/apt/lists/* \
&& pecl install imagick \
&& docker-php-ext-enable imagick

RUN apt-get update && apt-get install -y --no-install-recommends \
vim \
&& rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y --no-install-recommends \
libfreetype-dev \
libjpeg62-turbo-dev \
libpng-dev \
libwebp-dev \
libzip-dev \
libicu-dev \
libbz2-dev \
libgmp10 \
libgmp-dev \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-configure intl \
&& docker-php-ext-configure bcmath --enable-bcmath \
&& docker-php-ext-configure gmp --with-gmp \
&& docker-php-ext-configure sysvsem --enable-sysvsem \
&& docker-php-ext-install -j$(nproc) gd zip pdo_mysql bz2 intl exif opcache sysvsem gmp bcmath

RUN { \
echo 'memory_limit=512M'; \
echo 'post_max_size=512M'; \
echo 'upload_max_filesize=512M'; \
} > /usr/local/etc/php/conf.d/docker-php-memlimit.ini;

RUN { \
echo 'apc.enable_cli=1'; \
} > /usr/local/etc/php/conf.d/apcu.ini;

# Set recommended opcache php.ini settings
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=2'; \
echo 'opcache.fast_shutdown=1'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini

# Configure-error-logging
RUN { \
echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR'; \
echo 'display_errors = Off'; \
echo 'display_startup_errors = Off'; \
echo 'log_errors = On'; \
echo 'error_log = /dev/stderr'; \
echo 'log_errors_max_len = 1024'; \
echo 'ignore_repeated_errors = On'; \
echo 'ignore_repeated_source = Off'; \
echo 'html_errors = Off'; \
} > /usr/local/etc/php/conf.d/error-logging.ini

RUN echo 'alias ll="ls -la"' >> ~/.bashrc;

创建一个 network,便于 container 间的相互访问

1
docker network create my-dockers-network

php-fpm 的一些配置 zz-docker.conf,下边启动 php-fpm 时会用

1
2
3
4
5
6
7
8
9
10
[global]
daemonize = no

[www]
listen = 9000
pm = dynamic
pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25

php-fpm 的 docker-compose-php.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.8'
services:
php:
container_name: php-fpm
image: php:8-fmp_zip_gd
deploy:
resources:
limits:
memory: 600M
reservations:
memory: 512M
restart: always
volumes:
- /my_home/nginx-proxy-manager/php-config/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf
- /my_home/nginx-proxy-manager/www:/var/www:rw # 下载 Nextcloud 放到这个目录下
- /my_home/nextcloud/data:/var/nextcloud:rw # Nextcloud 数据保存目录
expose:
- 9000
networks:
- my-dockers-network

networks:
my-dockers-network:
external: true

php-fpm 启动后, docker exec -it php-fpm bash 进入容器,然后 chown 33:33 -R html 修改目录归属,否则 php-fmp 会报无权限写入 config

Nignx Proxy Manager(以下简称 NPM) 的 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3.8'
services:
nginx-proxy-manager:
container_name: nginx-proxy-manager
image: 'jc21/nginx-proxy-manager:latest'
restart: always
ports:
- '8880:80'
- '8881:81'
- '8443:443'
volumes:
- /my_home/nginx-proxy-manager/data:/data
- /my_home/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
- /my_home/nginx-proxy-manager/www:/var/www # 和 php container 共享
networks:
- my-dockers-network

networks:
my-dockers-network:
external: true

在 NPM 的 /data/nginx/custom/http_top.conf 中添加:

1
2
3
4
5
# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
"" "";
default "immutable";
}

NPM 中配置对应的 Proxy Host(注意:不要开 Cache Assets)

还要在 Advanced 中进行如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
root /var/www/html/nextcloud;

server_tokens off;

client_max_body_size 512M;
client_body_timeout 300s;
fastcgi_buffers 64 4K;

# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

client_body_buffer_size 512k;

# HTTP response headers borrowed from nextcloud `.htaccess`
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;

# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;

index index.php index.html /index.php$request_uri;

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 $scheme://$http_host/remote.php/webdav/$is_args$args;
}
# http -> https
error_page 497 301 =307 https://$http_host$request_uri;
}

location ^~ /.well-known {
location = /.well-known/carddav { return 301 $scheme://$http_host/remote.php/dav/; }
location = /.well-known/caldav { return 301 $scheme://$http_host/remote.php/dav/; }

location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }

return 301 $scheme://$http_host/index.php$request_uri;
}

location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }

location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;

fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;

try_files $fastcgi_script_name =404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_pass php-fpm:9000;

fastcgi_intercept_errors on;
fastcgi_request_buffering off;

fastcgi_max_temp_file_size 0;
}

# Serve static files
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463, $asset_immutable";
access_log off; # Optional: Don't log access to assets

location ~ \.wasm$ {
default_type application/wasm;
}
}

location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}

# Rule borrowed from `.htaccess`
location /remote {
return 301 /remote.php$request_uri;
}

location / {
try_files $uri $uri/ /index.php$request_uri;
}

/etc/config/crontab 里添加定时任务(以威联通 QTS 系统为例,其他系统自行调整)

1
*/5 * * * * /share/CACHEDEV1_DATA/.qpkg/container-station/bin/docker exec -u www-data php-fpm php /var/www/html/nextcloud/cron.php >/dev/null 2>&1

并使用 crontab /etc/config/crontab 生效

其中的 docker 路径可以通过 which docker 找到

客户端修改域名端口

在 server 端修改域名后,客户端只需修改配置文件里的域名即可,不用重新配置。

在对应系统下,先关闭 Nextcloud 程序,然后找到 cfg 文件修改 URL 即可。再启动 Nextcloud 后,会自动弹框要求登录授权,和之前那个账户一致,然后授权即可。

Linux: $HOME/.config/nextcloud/nextcloud.cfg

Windows: %APPDATA%\nextcloud\nextcloud.cfg

macOS: $HOME/Library/Preferences/nextcloud/nextcloud.cfg


Slef-Hosted:Nextcloud 部署
https://www.haoyizebo.com/posts/c37cbd62/
作者
一博
发布于
2023年10月27日
许可协议