现在的网盘越来越辣鸡,倒不是说体验不好,天朝带宽这么贵的情况下,30一个月也还算划算(暗示),但天天扫描网盘上的文件就不能忍了😕,毕竟不是每个人都愿意用隐私换取便利(再次暗示),因此剁手购入大盘独服,自己搭建一个网盘使用。在平台的选择过程中最后纠结于Nextcloud和Seafile,都搭建体验之后最终选择了Seafile,比较PHP的文件管理性能略显拉跨。

Seafile是一款开源的企业云盘,注重可靠性和性能。支持Windows, Mac, Linux, iOS, Android多平台文件同步或者直接挂载到本地访问。专业版也免费支持最多三个用户,足以满足要求,顺便试一下用Docker部署,第一次使用Docker也遇到了一些坑,也作为记录。

安装Docker

可以查看官方文档说明,推荐直接使用仓库安装。

添加Docker的仓库:

yum install -y yum-utils
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装最新的版本Docker:

yum install docker-ce docker-ce-cli containerd.io

运行Docker,并用helloworld测试是否正确:

systemctl start docker
docker run hello-world

输入命令后将会自动运行测试镜像并打印退出

安装docker-complse:
为了方便部署项目,再安装docker-compose

yum install docker-compose -y

部署Seafile专业版

从Seafile官网下载docker-complse.yml修改后上传到服务器上。

特别注意的是要修改以下几项配置:

  • MySQL root用户的密码
  • 持久化存储MySQL数据的volumes目录
  • 持久化存储Seafile数据的volumes目录
  • 持久化存储Elasticsearch索引数据的volumes目录

接着在docker-compose.yml目录下使用以下命名启动Seafile:

docker-compose up -d

按照官方文档的说法是现在就可以的输入地址访问了,可是却发现一直502,最后使用docker logs --since 30m [CONTAINER_ID]查看日志,发现数据库一直连不上,连接一直被拒绝,研究了半天,这是因为在CentOS7上部署Docker,网络模式采用的是bridge模式,启动Docker时,会创建一个名为docker0的虚拟网桥,用于宿主机与容器之间的通信。

如果Docker容器访问宿主机,那么docker0网桥将报文直接转发到本机,报文的源地址是docker0网段的地址。而如果 docker 容器访问宿主机以外的机器,docker 的 SNAT 网桥会将报文的源地址转换为宿主机的地址,通过宿主机的网卡向外发送。因此,当Docker容器访问宿主机时,如果宿主机服务端口会被防火墙拦截,那么就无法连通宿主机。

为了解决这个问题,首先使用ifconfig查看网络地址,编辑/etc/firewalld/zones/public.xml文件,添加docker0和使用docker-compose命令生成的地址段:

<rule family="ipv4">
  <source address="172.18.0.0/16"/>
  <accept/>
</rule>

之后使用docker ps查看安装的镜像,卸载seafile镜像重新运行docker-comple up -d

docker stop [seafile ID]
docker rm [seafile ID]
docker rmi [seafile ID]
docker-comple up -d

等待安装完成之后就可以正常访问了

使用https访问

Seafile自带了开启https的选项,用的是Let's encryption,这里选择使用自己的证书通过外部Nginx反代

server {
    listen 80;
    server_name domain.com;
    rewrite ^(.*)$  https://$host$1 permanent; 
}

server {
    listen 443 ssl http2;
    server_name domain.com;
    ssl_certificate /[path]/full_chain.pem; 
    ssl_certificate_key /[path]/private.key;
    #TLS 版本控制
    ssl_protocols   TLSv1.3;
    ssl_ciphers     TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256;
    ssl_prefer_server_ciphers   on;
    # 开启 1.3 0-RTT
    ssl_early_data  on;
    ssl_stapling on;
    ssl_stapling_verify on;

    location / {
        proxy_pass https://127.0.0.1:[port];  # 设置为docker seafile映射出来的https端口
        proxy_set_header  Host $host:$server_port;
        proxy_set_header  X-Real-IP  $remote_addr;
        client_max_body_size  10m;
    }
}

接下来修改Docker中Nginx的配置,如果持久化存储Seafile数据的目录为/opt/seafile-data

创建/opt/seafile-data/ssl目录,然后拷贝证书文件和密钥文件到ssl目录下

接着修改配置文件/opt/seafile-data/nginx/conf/seafile.nginx.conf注意不要更改该配置文件的文件名:

server {
    listen 80;
    server_name domain;
    rewrite ^ https://$host$request_uri? permanent;
    server_tokens off;
}

server {
    listen 443 ssl http2;
    server_name domain;
    ssl on;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:5m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_certificate      /shared/ssl/full_chain.pem;
    ssl_certificate_key  /shared/ssl/private.key;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS';
    ssl_prefer_server_ciphers on;

    proxy_set_header X-Forwarded-For $remote_addr;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
    server_tokens off;

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_read_timeout 310s;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Forwarded-Proto $scheme;

        client_max_body_size 0;
        access_log      /var/log/nginx/seahub.access.log seafileformat;
        error_log       /var/log/nginx/seahub.error.log;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 0;
        proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_request_buffering off;
        access_log      /var/log/nginx/seafhttp.access.log seafileformat;
        error_log       /var/log/nginx/seafhttp.error.log;
    }

    location /seafdav {
        proxy_pass         http://127.0.0.1:8080;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout  1200s;
        client_max_body_size 0;

        access_log      /var/log/nginx/seafdav.access.log seafileformat;
        error_log       /var/log/nginx/seafdav.error.log;
    }

    location /media {
        root /opt/seafile/seafile-server-latest/seahub;
    }

    # For letsencrypt
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }
}

重启两处Nginx:

systemctl restart nginx.service
docker exec -it seafile /usr/sbin/nginx -s reload

之后就可以通过https访问了,然后发现上传不了文件,又研究了半天,需要修改 系统管理 -> 设置 页面中的两个url设置的地址才行。

然后又发现登陆后就提示不安全,证书正常加载,Chrome中查看发现引用了错误的http地址导致,试了很多方法都不行,最后试了下使用rm -rf /tmp/seahub_cache删除seahub的缓存文件才解决,,然后又发现头像一直无法加载,发现头像的地址为https://domian:8080,又回头看设置中的home-url后面多了8080。。去掉之后重启docker-compose restart后终于正常了QAQ

最后值得一提的是在Seafile中,当文件被删除时,组成这些文件的块数据不会立即删除,因为可能有其他文件也会引用这些块数据(用于去重功能的实现)。为了真正删除无用的块数据,还需要额外运行"GC"程序。GC 会自动检测到哪些数据块不再被任何文件所引用,并清除它们。

docker exec seafile /scripts/gc.sh

Tags: Linux, Seafile, Docker

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.