1. 为什么在2020年这个时间点,我依然选择用CentOS 7搭Seafile
先把时间线拉回到2020年8月。那会儿公有网盘的个人限速策略越来越紧,免费容量看着大,实际传点大文件就原形毕露。我手上有一台闲置的物理服务器,配置不算新,但胜在硬盘够大、带宽独享,于是动了自建私有云盘的念头。选型阶段我对比过Nextcloud、ownCloud和Seafile,最后落在Seafile上,核心原因就三条:同步逻辑是块级别的、对服务器性能要求低、文件历史版本管理做得扎实。
Seafile和Nextcloud最大的区别在于同步机制。Nextcloud走的是整文件同步,你改一个几十兆的文档里一个标点,它可能把整个文件重新传一遍。Seafile则是把文件切块,只传变化的那部分块,这个设计对经常改大文件、又用着上行带宽有限的家宽用户来说,体验差距是肉眼可见的。另外Seafile的服务端用C语言写核心、Python做Web层,内存占用比PHP系的方案要克制不少,我那台老机器跑起来压力小很多。
至于为什么是CentOS 7而不是Ubuntu,纯粹是当时这台服务器上已经跑着别的业务,系统就是CentOS 7,我不想为了一个网盘重装系统。CentOS 7在2020年还是主流的企业级发行版,软件源稳定、文档齐全,虽然它的生命周期后来大家都知道会结束,但在当时那个节点,它是个稳妥的选择。这篇文章就是把我从零搭建到跑通的完整过程、踩过的坑、以及后来维护中总结的经验,原原本本讲一遍。
需要提前说明的是,Seafile的部署方式有几种:用官方安装脚本、用Docker、或者手动编译。我选的是官方脚本 + 手动调整的混合路线,因为纯脚本有时候会帮你做一些你不想要的默认配置,而纯手动又太费时间。下面会详细说每一步为什么这么做。
2. 搭建前的环境盘点与依赖梳理
2.1 服务器基础配置的确认清单
动手之前,先把家底摸清楚。我用的是一台单路服务器,配置大致是4核CPU、8GB内存、一块240GB的SSD做系统盘、两块4TB的机械盘做数据盘。这个配置对Seafile来说绰绰有余,官方对社区版的最低要求其实很低,1核2GB就能跑起来,但那是"能跑",不是"好用"。
你需要确认几件事:系统版本、内存大小、磁盘挂载情况、防火墙状态、以及SELinux的状态。CentOS 7默认开启SELinux和firewalld,这两个东西在部署Web服务时经常出来捣乱,我建议在测试阶段先把SELinux设为permissive模式,等全部跑通后再根据实际情况决定是否收紧。命令很简单:
getenforce # 如果返回 Enforcing,临时改成 Permissive setenforce 0 # 永久生效需要改配置文件 sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config磁盘方面,我强烈建议把Seafile的数据目录单独挂载到数据盘上,不要和系统盘混在一起。原因很直接:网盘的数据会越来越大,系统盘通常不大,一旦写满,整个系统都可能出问题。我当时的做法是把两块4TB盘做了软RAID或者LVM,挂到/data目录,然后Seafile的所有数据都放在/data/seafile下面。
2.2 依赖包的安装与版本选择
Seafile的服务端依赖Python 2.7(注意,2020年那会儿社区版还是Python 2.7为主,Python 3的支持在后续版本才完善),以及MySQL或MariaDB、Nginx或Apache。我选的是MariaDB + Nginx的组合,理由是MariaDB在CentOS 7的源里就是默认的MySQL替代品,兼容性好;Nginx处理静态文件比Apache轻快,配置也更直观。
安装依赖的命令如下:
yum install -y epel-release yum install -y mariadb-server mariadb nginx python2 python2-devel \ python-setuptools gcc gcc-c++ make libffi-devel openssl-devel \ MySQL-python python-imaging这里有个细节要注意:MySQL-python这个包在有些源里可能叫python2-mysql,如果装不上,可以试试yum provides */MySQLdb来找对应的包。另外python-imaging是Pillow的前身,Seafile生成缩略图会用到,别漏了。
提示:CentOS 7的默认源里Python就是2.7,不要手贱去升级成Python 3,否则Seafile的启动脚本会因为语法不兼容直接报错。这是我在第一次部署时踩的坑,折腾了半天才发现是Python版本问题。
2.3 数据库的初始化与安全设置
MariaDB装好后,先启动并设置开机自启:
systemctl start mariadb systemctl enable mariadb mysql_secure_installationmysql_secure_installation这个交互脚本会引导你设置root密码、删除匿名用户、禁止root远程登录等,一路按推荐选项走就行。然后登录数据库,为Seafile创建专用的数据库和用户:
CREATE DATABASE seafile_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE ccnet_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE seahub_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON seafile_db.* TO 'seafile'@'localhost' IDENTIFIED BY '你的强密码'; GRANT ALL PRIVILEGES ON ccnet_db.* TO 'seafile'@'localhost' IDENTIFIED BY '你的强密码'; GRANT ALL PRIVILEGES ON seahub_db.* TO 'seafile'@'localhost' IDENTIFIED BY '你的强密码'; FLUSH PRIVILEGES;三个库的分工是这样的:ccnet_db存的是节点间通信和用户基础信息,seafile_db存文件元数据和块信息,seahub_db存Web界面相关的用户、群组、分享等数据。字符集一定要用utf8mb4,不然用户上传带emoji的文件名或者中文名时会出现乱码,这个坑我替你们踩过了。
3. Seafile服务端的下载、解压与核心配置
3.1 安装包的选择与目录规划
Seafile社区版的安装包在官方下载页有提供,2020年那会儿主流版本是7.1.x系列。我选的是seafile-server_7.1.5_x86-64.tar.gz这个版本,没有追最新的7.1.6,因为7.1.5的社区反馈更稳定,而且我查过它的更新日志,没有修复我关心的关键问题,所以没必要冒险。
目录规划上,我建议这样安排:
/data/seafile/ ├── seafile-server-7.1.5/ # 程序目录 ├── seafile-data/ # 核心数据目录 ├── seahub-data/ # Web端数据 ├── seafile-server-latest -> seafile-server-7.1.5 # 软链接 └── ccnet/ # 通信配置把安装包解压到/data/seafile/下,然后创建软链接seafile-server-latest指向具体版本目录。这样做的好处是,将来升级时只需要解压新版本、改软链接指向,回滚也方便。
mkdir -p /data/seafile cd /data/seafile tar -xzf seafile-server_7.1.5_x86-64.tar.gz ln -s seafile-server-7.1.5 seafile-server-latest3.2 运行初始化脚本时的关键选择
进入seafile-server-latest目录,执行./setup-seafile-mysql.sh。这个脚本会问你几个问题,每一个都值得说清楚:
- 服务器名称:随便起,但建议用有意义的英文名,比如
mycloud,它会显示在客户端里。 - 服务器IP或域名:如果你有域名,直接填域名;没有就填服务器内网IP。注意,这里填的地址会写进配置文件,将来换域名要改配置,所以想清楚再填。
- 数据目录:默认是脚本所在目录的上一级,我改成了
/data/seafile/seafile-data,和程序目录分开。 - 端口:默认
8082是文件服务端口,8000是Web端口。这两个端口后面要在Nginx里做反向代理,先记着。
数据库那一步,选择"使用已有的MySQL数据库",然后填入之前创建的库名、用户名和密码。脚本会自动建表,看到Successfully created seafile server就说明初始化成功了。
3.3 seafile.conf与seahub_settings.py的调优
初始化完成后,有两个配置文件值得动手改一改。
第一个是conf/seafile.conf,我主要调整了文件大小限制和过期清理策略:
[fileserver] # 单文件上传上限,默认是100M,我改成了2G max_upload_size = 2048 # 上传下载的限速,单位是KB/s,0表示不限 max_download_rate = 0 max_upload_rate = 0 [history] # 文件历史保留天数,默认是永久,我改成180天,省空间 keep_days = 180第二个是conf/seahub_settings.py,这个是Web端的配置,我加了几个实用项:
# 关闭注册,只允许管理员创建账号 ENABLE_SIGNUP = False # 设置站点标题 SITE_NAME = '我的私有云盘' SITE_TITLE = '我的私有云盘' # 文件预览相关的配置 FILE_PREVIEW_MAX_SIZE = 50 * 1024 * 1024ENABLE_SIGNUP = False这个设置很重要,私有云盘如果开着公开注册,等于把大门敞开,谁都能来注册账号。关掉之后,账号只能由管理员在后台手动创建,安全性高很多。
4. Nginx反向代理与HTTPS的落地细节
4.1 为什么必须用Nginx而不是直接暴露端口
Seafile自带的Web服务(seahub)性能一般,而且直接暴露8000端口有几个问题:没法方便地配HTTPS、静态文件处理效率低、不支持多站点共存。用Nginx做反向代理是标准做法,它负责处理SSL握手、静态资源缓存、以及把动态请求转发给后端的seahub。
我的Nginx配置大致如下,放在/etc/nginx/conf.d/seafile.conf:
server { listen 80; server_name your-domain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your-domain.com; ssl_certificate /etc/nginx/ssl/your-cert.pem; ssl_certificate_key /etc/nginx/ssl/your-key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; client_max_body_size 2048m; location / { proxy_pass http://127.0.0.1:8000; 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-Proto $scheme; } location /seafhttp { rewrite ^/seafhttp(.*)$ $1 break; proxy_pass http://127.0.0.1:8082; client_max_body_size 0; proxy_request_buffering off; } location /media { root /data/seafile/seafile-server-latest/seahub; } }这里有几个关键点:client_max_body_size要设得足够大,不然大文件上传会被Nginx直接拒掉;/seafhttp这个location是文件传输专用的,proxy_request_buffering off能让上传流式转发,不占Nginx的临时磁盘空间;/media直接由Nginx返回静态文件,减轻后端压力。
4.2 证书申请与自动续期的实操
2020年那会儿,Let's Encrypt的证书申请已经可以用certbot自动化了。我用的方式是certbot的Nginx插件:
yum install -y certbot python2-certbot-nginx certbot --nginx -d your-domain.comcertbot会自动改Nginx配置、申请证书、设置续期定时任务。续期测试可以用certbot renew --dry-run来验证。这里要注意,certbot的续期依赖80端口的验证,所以你的80端口必须能从公网访问,不能只开443。
注意:如果你的服务器前面还有一层路由器或者别的代理,80端口的映射要确保正确,否则证书续期会失败。我有个朋友就是因为路由器没做80端口映射,三个月后证书过期了才发现。
4.3 代理配置与Seafile的联动调整
Nginx配好后,还要回头改Seafile的两个配置,告诉它自己是在代理后面:
在conf/seahub_settings.py里加上:
USE_X_FORWARDED_HOST = True在conf/ccnet.conf里,把SERVICE_URL改成你的域名:
SERVICE_URL = https://your-domain.com这两步不做的话,会出现登录后跳转回内网IP、或者分享链接生成错误地址的问题。改完配置后,重启Seafile服务生效。
5. 服务启动、开机自启与日常运维脚本
5.1 启动顺序与常见启动失败排查
Seafile的启动分两步:先启动seafile(文件服务),再启动seahub(Web服务)。命令在seafile-server-latest目录下:
./seafile.sh start ./seahub.sh startseahub.sh start第一次启动时会让你创建管理员账号,填邮箱和密码就行。如果启动失败,去logs/目录下看日志,seafile.log和seahub.log会告诉你具体原因。常见的失败原因有:数据库连不上(检查密码和权限)、端口被占用(netstat -tlnp查一下)、Python依赖缺失(根据报错装对应的包)。
5.2 用systemd管理服务实现开机自启
官方脚本没有提供systemd单元文件,手动写一个更省心。创建/etc/systemd/system/seafile.service:
[Unit] Description=Seafile After=network.target mariadb.service [Service] Type=forking ExecStart=/data/seafile/seafile-server-latest/seafile.sh start ExecStop=/data/seafile/seafile-server-latest/seafile.sh stop User=root Group=root Restart=on-failure [Install] WantedBy=multi-user.target再创建seahub.service,内容类似,只是把脚本换成seahub.sh,并且After里加上seafile.service。然后systemctl daemon-reload、systemctl enable seafile seahub就搞定了。
5.3 备份策略:数据库和数据的分离备份
私有云盘最怕的就是数据丢失,备份必须做。我的策略是数据库每天备份、数据目录每周增量备份。数据库备份用mysqldump:
mysqldump -u seafile -p'密码' --databases seafile_db ccnet_db seahub_db > /backup/seafile-db-$(date +%F).sql数据目录的备份,如果数据量大,用rsync做增量同步到另一块盘或者另一台机器:
rsync -avz --delete /data/seafile/seafile-data/ /backup/seafile-data/把这些命令写进crontab,定时执行。备份文件也要定期清理,不然磁盘会被撑满。我一般保留最近30天的数据库备份和最近4周的数据备份。
6. 那些文档里不会写的踩坑记录
6.1 上传大文件卡在99%的元凶
部署完没多久,我传一个1.5GB的镜像文件,进度条卡在99%不动,最后报错。查了半天,发现是Nginx的client_max_body_size虽然设了2G,但Seafile自己的max_upload_size单位是MB,我写成了2048,它认,但还有个隐藏限制在seahub_settings.py里的FILE_PREVIEW_MAX_SIZE和上传无关,真正卡住的是Nginx的proxy_read_timeout。默认60秒,大文件传久了就超时。加上proxy_read_timeout 3600s;和proxy_send_timeout 3600s;后问题解决。
6.2 中文文件名乱码的根因
有次同事上传了一批中文命名的文件,在Web界面显示正常,但下载到本地后文件名变成了一堆问号。排查后发现是数据库字符集的问题——我建库时用了utf8而不是utf8mb4,某些中文字符在utf8下存储不完整。解决办法是重建数据库并指定utf8mb4,然后把数据重新导入。这个教训告诉我,建库时的字符集选择是一锤子买卖,后面改起来非常麻烦。
6.3 内存占用随时间上涨的处理
跑了大概两个月后,我发现seafile-controller进程的内存占用从最初的200MB涨到了1.5GB。这不是内存泄漏,而是Seafile的缓存机制——它会缓存文件块索引来加速访问。解决办法是在seafile.conf里限制缓存大小:
[fileserver] # 缓存目录大小上限,单位MB cache_size_limit = 512设置后重启服务,内存占用就稳定下来了。如果你的服务器内存紧张,这个参数值得调小一点。
6.4 客户端同步冲突的预防
Seafile的同步机制虽然好,但多端同时改同一个文件时还是会产生冲突文件。我的经验是:养成"改前先同步、改完立即同步"的习惯,避免在离线状态下大改文件。另外,在团队协作场景下,尽量用"资料库"来划分不同项目,而不是所有人共享一个巨大的库,这样冲突范围可控。
7. 从能用走向好用:几个提升体验的进阶设置
7.1 邮件通知的配置
Seafile支持发邮件通知,比如分享文件、密码重置等。在seahub_settings.py里配置SMTP:
EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.example.com' EMAIL_HOST_USER = 'your-email@example.com' EMAIL_HOST_PASSWORD = 'your-password' EMAIL_PORT = 587 DEFAULT_FROM_EMAIL = 'your-email@example.com' SERVER_EMAIL = 'your-email@example.com'配好后,用户忘记密码可以自助重置,不用管理员手动干预。注意,很多邮件服务商对发信频率有限制,别拿它发垃圾邮件。
7.2 用OnlyOffice实现在线编辑
Seafile本身只支持预览,不支持在线编辑Office文档。要实现在线编辑,需要额外部署OnlyOffice Document Server,然后在Seafile里配置对接。这个部署稍微复杂,需要Docker环境,但效果很好——多人可以同时编辑一个文档,类似在线协作文档的体验。具体步骤这里不展开,但思路是:Docker跑OnlyOffice、Nginx配一个子域名指向它、Seafile里填上这个子域名地址。
7.3 移动端与桌面客户端的选型
Seafile官方提供了Windows、macOS、Linux、iOS、Android的客户端。桌面端我推荐用官方客户端,同步稳定;移动端的话,iOS和Android都有官方App,支持自动备份照片。如果你有大量照片要备份,可以在手机App里开启"相机上传",它会自动把新拍的照片同步到指定的资料库。
8. 关于这套方案的生命周期与迁移思考
CentOS 7在2024年6月已经停止维护,这是后来发生的事。但在2020年部署时,这套方案是合理且稳定的。如果你现在还在用CentOS 7跑Seafile,我的建议是尽早规划迁移,目标系统可以是Rocky Linux 9或者Ubuntu 22.04 LTS。迁移的核心是数据目录和数据库的搬迁,程序本身重新部署即可,数据是无价的。
迁移的大致思路:在新系统上装好相同版本的Seafile、建好数据库、停掉旧服务、把seafile-data和seahub-data目录rsync过去、导入数据库、改配置里的路径和地址、启动新服务验证。整个过程最耗时的是数据同步,如果数据量大,可以先用rsync做一次全量,然后停服务做一次增量,把停机时间压到最短。
我个人在实际操作中的体会是,自建私有云盘这件事,部署只是开始,运维才是长期功课。定期看日志、定期备份、定期更新安全补丁,这三件事做到位,它就能安安稳稳地为你服务很多年。别指望搭完就一劳永逸,任何系统都需要照料,这跟养花是一个道理。