从零搭建 NextCloud 记录

2020-11-05 19点热度 0人点赞 0条评论

NextCloud 作为著名的开源私有云,一直饱受好评,而许多搭建过程也一直饱受"好评"进而都开始使用 docker。本文记录本站搭建的过程,期间埋坑一堆


1、选材

从头开始,那么肯定要选最新的系统了,CentOS 8 安排上! Ubuntu 20.04 安排上!

先到官网看看,哦,LAMPR,不行啊,Apache 动态去管理云盘静态资源?怎么想都亏爆啊

继续看看,脚本安装,啊这估计是给白板机准备的,像我们这些老油条肯定得是【自定义】

先准备下环境吧,CentOS 8 Ubuntu 20.04 + Nginx v1.18 + PHP-FPM v7.4 + Mysql 8.0 + Redis 5 + NextCloud


2、搭建

2.1、初逢

最开始我是直接把 Wordpres 的 LNMP 组件直接放上用,结果……惨遭毒打

刚开始看来还是很良心的,CentOS 还有案例支持,多好,赶紧安排上 [ 文档链接 ](本分支结局爆炸已删)

NextCloud 调用了大量的 PHP 相关组件,这些远远不是 Wordpres 所需要的那一丢丢的 PHP 组件所能比拟的。

Docker 环境的官方 PHP 包也缺少大量组件,必须额外增加。目前没有什么办法能让我在短时间安装好 NextCloud 巨量的组件支持 并且还不会报错,所以放弃 最终发现其实都是参数配置出错

无奈之下,只能先放弃了 Docker 环境 与 生产环境 直接搭建的想法


2.2、开始

老司机一般为了保证开车平稳,都是用的最熟悉的东西

那在 Linux 中,大家最常见的东西,肯定是 包管理器 apt-get

apt install nginx-full mysql-server mysql-client redis redis-server

PHP 中间摸爬滚打太多,干脆最后安装上的包都整理在这里好了。注意 PHP 版本是 7.4 的

apt install php-bcmath php-common php-curl php-fpm php-gd php-gmp php-igbinary php-imagick php-imap php-json php-mbstring php-redis php-zip
[关联] apt install php7.4 php7.4-bcmath php7.4-cli php7.4-common php7.4-curl php7.4-fpm php7.4-gd php7.4-gmp php7.4-imap php7.4-intl php7.4-json php7.4-ldap php7.4-mbstring php7.4-mysql php7.4-opcache php7.4-readline php7.4-xml php7.4-zip

那么按照该环境开始改配置。本文所使用的配置文件位置如下

Nginx 部分
用户 nginx:nginx
配置文件 /etc/nginx/nginx.conf
站点文件 /etc/nginx/site-enabled/nextcloud.conf
站点路径 /opt/nextcloud/
存储路径 /opt/nextcloud_data/

PHP-FPM 部分
用户 nginx:nginx
配置文件 /etc/php/7.4/fpm/php.ini;/etc/php/7.4/fpm/pool.d/www.conf
链接文件 /etc/php/7.4/fpm/conf.d/*.ini
会话文件 /var/lib/php/sessions
传输文件 /var/run/php-fpm.sock

Mysql 部分
用户 mysql:mysql
配置文件 /etc/mysql/mysql.conf.d/mysqld.cnf
数据文件 /var/lib/mysql/
传输文件 /var/run/mysqld/mysqld.sock

Redis 部分
用户 redis:redis
配置文件 /etc/redis/redis.conf
数据文件 /var/lib/redis/dump.rdb
传输文件 /var/run/redis/redis.sock

2.3、Nginx 配置

Nextcloud 官方给了 Nginx 配置文件方案,直接照抄即可 [ 链接 ]

……直接抄……

注意需要修改 root 参数,指向有效的本地文件

root /opt/nextcloud;

额外建议分离 站点日志 ,需要增加在 server{} 中

access_log  /var/log/nginx/nextcloud.log  main;
error_log  /var/log/nginx/nextcloud-error.log;

2.4、Mysql 配置

首先优先在 Mysql 配置文件中增加如下字段,并重启 Mysql 服务器
前三条字段是限制储存数据格式,同时允许 4bit emoji 字符写入数据库。
第四个是关闭 binlog 的产生(集群则不需要关闭)

[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
innodb_file_per_table=1
skip-log-bin

然后登陆数据库,并初始化 'root'@'localhost' 密码

mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass4!';

增加数据库用户 cloudmanager 并配置密码为 MyNewPass2!
增加数据库 nextclouddb 并为 cloudmanager 附加权限

CREATE USER 'cloudmanager'@'localhost' IDENTIFIED BY 'MyNewPass2!';
CREATE DATABASE IF NOT EXISTS nextclouddb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextclouddb.* TO 'cloudmanager'@'localhost';
FLUSH PRIVILEGES;

退出并使用新用户登录并测试数据库访问情况,测试好后退出

mysql -uroot -p
show databases;

2.5、PHP-FPM 配置

首先我们需要配置 php.ini 这个主体文件。

在这里其实有较多配置,但是我使用的大部分都不是主要的,关注主要的内容即可

memory_limit = 512M
error_log = /var/log/php7.4_error.log
post_max_size = 100M
upload_max_filesize = 100M
date.timezone = PRC
pdo_mysql.default_socket="/var/run/mysqld/mysqld.sock"
mysqli.default_port = 3306
mysqli.default_socket = "/var/run/mysqld/mysqld.sock"
session.save_handler = redis
session.save_path = "unix:/var/run/redis/[email protected]"
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=1
opcache.save_comments=1
opcache.huge_code_pages=1

接着我们需要配置 www.conf 的 php-fpm 线程文件,同样也是关注主要内容即可

注意其中下面五条其实和上面的 php.ini 重复,主要是在使用集群时需要自定义配置
中间 slowlog 和 request_slowlog_timeout 是慢查询日志,如果 php 出现 3s 以上的操作会记录

user = nginx
group = nginx
listen = /var/run/php-fpm.sock
listen.backlog = 2048
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18
slowlog = /var/log/php7.4-$pool-slow.log
request_slowlog_timeout = 3
php_admin_value[error_log] = /var/log/php74-$pool-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = redis
php_value[session.save_path]    = "unix:/var/run/redis/[email protected]"
php_value[soap.wsdl_cache_dir]  = "/tmp"

2.6、Redis 配置

在 Redis 中也需要同样配置,一共五条。
关闭 TCP 端口
开放 Socket 传输文件,以及赋予权限为 rw-rw----
配置 Redis 密码 本例为 [email protected] 上方曾经用到
增加 Redis 最大分配内存

port 0
unixsocket /var/run/redis/redis.sock
unixsocketperm 660
requirepass [email protected]
maxmemory 512mb

配置完后,我们还需要额外给 php-fpm 访问 redis.sock 的权限,方式是为 nginx 增加权限组

usermod -G redis nginx

如果 Redis 运行时提示一些内容,可以检查一下相关提示并根据提示进行优化操作。

Redis 测试命令

redis-cli -s /var/run/redis/redis.sock
auth [email protected]

2.7、NextCloud 权限配置

解压 NextCloud 文件至 /opt/nextcloud/ 可以检查到 /opt/nextcloud/version.php 存在

unzip nextcloud.zip
mv ./nextcloud /opt/
chown -R nginx:nginx /opt/nextcloud/

创建存储路径 /opt/nextcloud_data/ 并附加权限

mkdir /opt/nextcloud_data
chown -R nginx:nginx /opt/nextcloud_data/

2.8、NextCloud 配置

上方的内容汇总,直接在初始化界面填入即可

用户 : 
密码 : 

存储路径 : /opt/nextcloud_data

数据库用户 cloudmanager
数据库密码 MyNewPass2!
数据库库名 nextclouddb
数据库主机 localhost

生成的配置文件类似如下

   'instanceid' => 'qwertyuiop',
   'passwordsalt' => 'asdfghjkl',
   'secret' => 'zxcvbnm',
   'trusted_domains' =>
   array (
     0 => 'cloud.domain.com',
   ),
   'datadirectory' => '/opt/nextcloud_data',
   'dbtype' => 'mysql',
   'version' => '21.0.1.1',
   'overwrite.cli.url' => 'https://cloud.domain.com',
   'dbname' => 'nextclouddb',
   'dbhost' => 'localhost',
   'dbport' => '',
   'dbtableprefix' => 'oc_',
   'mysql.utf8mb4' => true,
   'dbuser' => 'cloudmanager',
   'dbpassword' => 'MyNewPass2!',
   'installed' => true,
   'debug' => false,

3、奇葩 BUG 汇总

3.0、排查方案

首先优先开启 log 模式

php.ini     ->  display_errors on(默认 应该 off)
redis.conf  ->  loglevel debug(默认 notice)
config.php  ->  'debug' => true,  (默认 false)
nextcloud   ->  /opt/nextcloud_data/nextcloud.log  (也可能在站点目录里)

3.1、无限登录循环

现象:是登录按钮点击后,页面刷新,又回来没变
原理:本质是 Redis 写入 session 失败,所以登录失效
处置:检查 Redis 运行情况即可。

本人 OS:chmod 644 /etc/redis/redis.conf 坑一年


3.2、消息传递被阻拦

现象:消息通知清理失败,新建出错,删除出错,编辑资料自动失效,却有一些小东西可以用
原理:NextCloud 使用了 method 除常规 (GET|HEAD|POST) 外的 (PUT|DELETE) 操作
处置:取消限制 method 的规则

本人 OS:撞 Nginx 规则还是真头一回。


4、其他配置

4.1、NextCloud 集群配置

在 站点文件/config/config.php 中增加如下字段,支持 redis 集群。

  'memcache.distributed' => '\OC\Memcache\Redis',
  'redis' => [
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'dbindex' => 0,
    'password' => '4e1fa509f485e548e789f9ddba6eba62d68037467f23dbe362077eba6a592f6c',
    'timeout' => 1.5,
  ],
  'memcache.locking' => '\OC\Memcache\Redis',

注意,config.php 的上下格式是有优先级的。少的时候可能会直接报错

在 php.ini 中增加 redis session 慢写入和锁定的配置

redis.session.locking_enabled=1
redis.session.lock_retries=-1
redis.session.lock_wait_time=10000

在 Mysql 配置文件中也需要增加一部分,比如去掉之前的

[mysqld]
#skip-log-bin
transaction_isolation = READ-COMMITTED
binlog_format = ROW
#innodb_large_prefix=on                #mysql8 失效
#innodb_file_format=barracuda          #mysql8 失效
innodb_buffer_pool_size=256M
innodb_io_capacity=4000

4.2、Docker 下去除 index.php 的链接字样

当你看到 domain.com/index.php/hello.txt 这样的 URL 感到十分苦恼,可以通过修改配置文件撤掉该字样。

第一种方案是修改 URL 重写规则,建议采用此方案 [ 链接 ]

<IfModule mod_rewrite.c>
  Options -MultiViews
  RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
  RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
  RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$
  RewriteCond %{REQUEST_FILENAME} !core/img/favicon.ico$
  RewriteCond %{REQUEST_FILENAME} !/remote.php
  RewriteCond %{REQUEST_FILENAME} !/public.php
  RewriteCond %{REQUEST_FILENAME} !/cron.php
  RewriteCond %{REQUEST_FILENAME} !/core/ajax/update.php
  RewriteCond %{REQUEST_FILENAME} !/status.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
  RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
  RewriteCond %{REQUEST_FILENAME} !/updater/
  RewriteCond %{REQUEST_FILENAME} !/ocs-provider/
  RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*
  RewriteRule . index.php [PT,E=PATH_INFO:$1]
  RewriteBase /
  <IfModule mod_env.c>
    SetEnv front_controller_active true
    <IfModule mod_dir.c>
      DirectorySlash off
    </IfModule>
  </IfModule>
</IfModule>

第二种方案是过去使用的,由于上方有好的方式所以不建议使用。同时仅能修改一部分的 URL,不是所有的都可以用这个方式修改。

./lib/private/URLGenerator.php 第 246 行附近
  public function getAbsoluteURL(string $url): string {
    $separator = strpos($url, '/') === 0 ? '' : '/';
    /** index_edit **/
    $url=str_replace("/index.php/","/",$url);

./config/config.php 新增一行
  'htaccess.RewriteBase' => '/',

4.3、安装 STUN/TURN 服务器

文章参考链接 [ 链接 ] 配置文件参数说明 [ 链接 ]

配置文件参考链接 [ 链接 ] 服务端测试方式 [ 链接 ]

apt install coturn

然后在 Ubuntu 中开启服务器

sed -i '/TURNSERVER_ENABLED/c\TURNSERVER_ENABLED=1' /etc/default/coturn
systemctl enable coturn.service
systemctl start coturn.service

接着修改配置文件 /etc/turnserver.conf

#syslog    默认自带的配置文件仅开启了 syslog 一个参数

# 配置 turn 监听接口(可选),turn 监听端口,备用 turn 监听端口(可选),turns 监听端口(可选),备用 (ALT)turns 监听端口(可选),以及内外网 NAT 地址(可选)如果备用端口未配置,默认为主端口号+1 的端口
# listening-device=eth0
# external-ip=101.202.102.201/192.168.1.100
listening-port=3478
alt-listening-port=3479
tls-listening-port=5349
alt-tls-listening-port=5350

fingerprint
lt-cred-mech

# 开启 NextCloud 所使用的 WebAuth 认证
use-auth-secret
# 配置 NextCloud 所使用的 WebAuth 认证密钥(时间密钥)(自行修改)
static-auth-secret=yoursecretpasswordqwertytuiop
# 配置本服务器所属域名(自行修改)
realm=your.domain.name

total-quota=100
bps-capacity=0
stale-nonce

# 配置 TLS 使用证书(自行修改)
cert=/etc/cert/fullchain.pem
pkey=/etc/cert/privkey.pem
# 配置自定义加密选择方式
# cipher-list="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5"

# 安全限制,禁用本地回复,禁用广播回复,禁止 DTLS(UDP 方式的 TLS 加密),禁止 TLSV1.0/1.1
no-loopback-peers
no-multicast-peers
no-dtls
no-tlsv1
no-tlsv1_1
no-cli
# 输出日志
no-stdout-log
syslog
simple-log
log-file=/var/log/coturn.log

配置完重启服务器,开放防火墙对应端口(以下仅开启了 turn 监听端口)(UDP 无认证可以选择不开)

firewall-cmd --zone=public --per --add-port=3478/tcp
firewall-cmd --zone=public --per --add-port=3478/udp
firewall-cmd --reload

在服务端配置页面中,进入 后台管理页面,通话(talk),在 STUN 服务器 和 TURN 服务器 中填写对应的信息,并等待测试通过后保存即可。(使用非加密的 turn 是因为 nextcloud 的 webrtc 已经加密,并且不能很好支持 turns [ 链接 ])

stun:your.domain.name:3478
turn:your.domain.name:3478 yoursecretpasswordqwertytuiop tcp/udp

在检测网站中,清空默认的 Google stun server,然后手动添加本次搭建的 STUN 服务器,URI 需要携带前缀 stun:yourdomainname:port
检测网站 [ 链接 ] WebRTC 测试网站 [ 链接 ]

点击 Gather candidates 按钮开始测试,等待下方出现 host 和 srflx 发送接收两条消息,即为正常使用。


4.4、新用户云盘默认文件

Nextcloud 创建用户时,会自动复制 core/skeleton 中的文件到新用户目录下。

所以如果需要修改默认用户云盘的文件内容,可以直接清空这个数据。

StarryVoid

这个人很懒,什么都没留下