# Seafile服务器

***

## Introduction

Seafile 是一个开源的文件云存储平台，解决文件集中存储、同步、多平台访问的问题，注重安全和性能。

Seafile 通过“资料库”来分类管理文件，每个资料库可单独同步，用户可加密资料库， 且密码不会保存在服务器端，所以即使是服务器管理员也无权访问你的文件。

Seafile 允许用户创建“群组”，在群组内共享和同步文件，方便了团队协同工作。

## Seafile服务器组件

Seafile 包含以下系统组件：

* Seahub：网站界面，供用户管理自己在服务器上的数据和账户信息。Seafile服务器通过"gunicorn"（一个轻量级的Python HTTP服务器）来提供网站支持。Seahub作为gunicorn的一个应用程序来运行。
* **Seafile server**(`seaf-server`):数据服务进程, 处理原始文件的上传/下载/同步。
* **Ccnet server**(`ccnet-server`):内部 RPC 服务进程，连接多个组件。
* **Controller**:监控 ccnet 和 seafile 进程，必要时会重启进程。

下面这张图显示了将 Seafile 部署在**Nginx/Apache**后的架构。

<div align="center"><img src="https://289909999-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LjaLKAAC8FFPhhMZ-7U%2Fuploads%2Fgit-blob-d615d7478e5ba7432f239d47f126bbd76b263f87%2FSeafile-Nginx.png?alt=media" alt=""></div>

* 所有 Seafile 服务都可以配置在 Nginx/Apache 后面，由 Nginx/Apache 提供标准的 http(s) 访问。
* 当用户通过 seahub 访问数据时，seahub 通过 ccnet 提供的内部 RPC 来从 seafile server 获取数据。

## 部署Seafile服务器(使用MySQL/MariaDB)

> 所有安装都基于CentOS 7完成

* 安装MariaDB(MariaDB是MySQL的分支) 安装Mariadb 10.1或以上版本，必须先指定yum源。
* 配置yum源

```bash
# cd /etc/yum.repos.d/
# touch MariaDB.repo
# vim MariaDB.repo

# MariaDB 10.1 CentOS repository list - created 2016-05-12 09:28 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
```

* 安装MariaDB 10.1

```bash
# yum install MariaDB-server MariaDB-client

Retrieving key from https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
Importing GPG key 0x1BB943DB:
 Userid     : "MariaDB Package Signing Key <package-signing-key@mariadb.org>"
 Fingerprint: 1993 69e5 404b d5fc 7d2f e43b cbcb 082a 1bb9 43db
 From       : https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
```

```bash
# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
```

```bash
service mysql start
Starting mysql (via systemctl):                            [  OK  ]
service mysql status
SUCCESS! MySQL running (861)
```

* 部署和目录设计

下载**seafile-server\_6.1.2\_x86-64.tar.gz**到你的**home**目录下。目录结构如下：

```bash
mkdir zloudfile
mv seafile-server_6.1.2_x86-64.tar.gz zloudfile
cd zloudfile
tar -xzf seafile-server_6.1.2_x86-64.tar.gz
mkdir installed
mv seafile-server_6.1.2_x86-64.tar.gz installed
```

现在目录结构如下：

```bash
tree zcloudfile -L 2
zcloudfile
├── installed
│   └── seafile-server_6.1.2_x86-64.tar.gz
└── seafile-server-6.1.2
    ├── check_init_admin.py
    ├── reset-admin.sh
    ├── runtime
    ├── seaf-fsck.sh
    ├── seaf-fuse.sh
    ├── seaf-gc.sh
    ├── seafile
    ├── seafile.sh
    ├── seahub
    ├── seahub.sh
    ├── setup-seafile-mysql.py
    ├── setup-seafile-mysql.sh
    ├── setup-seafile.sh
    └── upgrade
```

这样设计目录的好处在于

* seafile相关的配置文件都可以放在**zcloudfile**目录下，便于集中管理。
* 后续升级时,你只需要解压最新的安装包到**zcloudfile**目录下。

## 安装Seafile服务器

安装 Seafile 服务器之前，请确认已安装以下软件

* MariaDB或者MySQL服务器(MariaDB是MySQL的分支)
* python 2.7(从Seafile 5.1开始，python版本最低要求为2.7)
* python-setuptools
* python-imaging
* python-mysqldb
* python-ldap
* python-urllib3
* python-memcache(或者python-memcached)

```bash
yum -y install epel-release
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
yum -y install python-imaging MySQL-python python-memcached python-ldap python-urllib3 ffmpeg ffmpeg-devel
pip install pillow moviepy
```

* 安装

```bash
cd seafile-server-6.1.2
./setup-seafile-mysql.sh
Checking python on this machine ...
  Checking python module: setuptools ... Done.
  Checking python module: python-imaging ... Done.
  Checking python module: python-mysqldb ... Done.

-----------------------------------------------------------------
This script will guide you to setup your seafile server using MySQL.
Make sure you have read seafile server manual at

        https://github.com/haiwen/seafile/wiki

Press ENTER to continue
-----------------------------------------------------------------


What is the name of the server? It will be displayed on the client.
3 - 15 letters or digits
[ server name ] Seafile

What is the ip or domain of the server?
For example: www.mycompany.com, 192.168.1.101
[ This server ip or domain ] 45.76.2.212

Where do you want to put your seafile data?
Please use a volume with enough free space
[ default "/home/zcloudfile/seafile-data" ]

Which port do you want to use for the seafile fileserver?
[ default "8082" ]

-------------------------------------------------------
Please choose a way to initialize seafile databases:
-------------------------------------------------------

[1] Create new ccnet/seafile/seahub databases
[2] Use existing ccnet/seafile/seahub databases

[ 1 or 2 ] 1

What is the host of mysql server?
[ default "localhost" ]

What is the port of mysql server?
[ default "3306" ]

What is the password of the mysql root user?
[ root password ]

verifying password of user root ...  done

Enter the name for mysql user of seafile. It would be created if not exists.
[ default "seafile" ]

Enter the password for mysql user "seafile":
[ password for seafile ]

Enter the database name for ccnet-server:
[ default "ccnet-db" ]

Enter the database name for seafile-server:
[ default "seafile-db" ]

Enter the database name for seahub:
[ default "seahub-db" ]

---------------------------------
This is your configuration
---------------------------------

    server name:            Seafile
    server ip/domain:       45.76.2.212

    seafile data dir:       /home/zcloudfile/seafile-data
    fileserver port:        8082

    database:               create new
    ccnet database:         ccnet-db
    seafile database:       seafile-db
    seahub database:        seahub-db
    database user:          seafile



---------------------------------
Press ENTER to continue, or Ctrl-C to abort
---------------------------------

Generating ccnet configuration ...

done
Successly create configuration dir /home/zcloudfile/ccnet.
Generating seafile configuration ...

Done.
done
Generating seahub configuration ...

----------------------------------------
Now creating seahub database tables ...

----------------------------------------

creating seafile-server-latest symbolic link ...  done




-----------------------------------------------------------------
Your seafile server configuration has been finished successfully.
-----------------------------------------------------------------

run seafile server:     ./seafile.sh { start | stop | restart }
run seahub  server:     ./seahub.sh  { start <port> | stop | restart <port> }

-----------------------------------------------------------------
If you are behind a firewall, remember to allow input/output of these tcp ports:
-----------------------------------------------------------------

port of seafile fileserver:   8082
port of seahub:               8000

When problems occur, Refer to

        https://github.com/haiwen/seafile/wiki

for information.

[root@zhaojun seafile-server-6.1.2]# ./seafile.sh start

[10/22/17 02:06:25] ../common/session.c(132): using config file /home/zcloudfile/conf/ccnet.conf
Starting seafile server, please wait ...
Seafile server started

Done.
[root@zhaojun seafile-server-6.1.2]# ./seahub.sh start

LC_ALL is not set in ENV, set to en_US.UTF-8
Starting seahub at port 8000 ...

----------------------------------------
It's the first time you start the seafile server. Now let's create the admin account
----------------------------------------

What is the email for the admin account?
[ admin email ] zhaojunhhu@gmail.com

What is the password for the admin account?
[ admin password ]

Enter the password again:
[ admin password again ]



----------------------------------------
Successfully created seafile admin
----------------------------------------




Seahub is started

Done.
```

现在的目录结构看起来应该是这样：

```bash
zcloudfile
├── ccnet
│   ├── ccnet.sock
│   ├── misc
│   ├── mykey.peer
│   └── seafile.ini
├── conf
│   ├── ccnet.conf
│   ├── seafdav.conf
│   ├── seafile.conf
│   ├── seahub_settings.py
│   └── seahub_settings.pyc
├── installed
│   └── seafile-server_6.1.2_x86-64.tar.gz
├── logs
│   ├── ccnet.log
│   ├── controller.log
│   ├── seafile.log
│   ├── seahub_django_request.log
│   └── seahub.log
├── pids
│   ├── ccnet.pid
│   └── seaf-server.pid
├── seafile-data
│   ├── commits
│   ├── fs
│   ├── httptemp
│   ├── library-template
│   ├── storage
│   └── tmpfiles
├── seafile-server-6.1.2
│   ├── check_init_admin.py
│   ├── reset-admin.sh
│   ├── runtime
│   ├── seaf-fsck.sh
│   ├── seaf-fuse.sh
│   ├── seaf-gc.sh
│   ├── seafile
│   ├── seafile.sh
│   ├── seahub
│   ├── seahub.sh
│   ├── setup-seafile-mysql.py
│   ├── setup-seafile-mysql.sh
│   ├── setup-seafile.sh
│   └── upgrade
├── seafile-server-latest -> seafile-server-6.1.2
└── seahub-data
    ├── avatars
    └── thumbnail
```

seafile-server-latest文件夹为指向当前Seafile服务器文件夹的符号链接,将来你升级到新版本后, 升级脚本会自动更新使其始终指向最新的Seafile服务器文件夹。

## 启动Seafile服务器

在 seafile-server-6.1.2 目录下，运行如下命令:

* 启动 Seafile

```bash
./seafile.sh start # 启动Seafile服务
```

* 启动 Seahub

```bash
./seahub.sh start <port>  # 启动Seahub网站 （默认运行在8000端口上）
```

> 第一次启动 seahub 时，seahub.sh 脚本会提示你创建一个seafile管理员帐号。

服务启动后，打开浏览器并输入地址：`http://45.76.2.212:8000`

## 在另一端口上运行Seahub

如果不想在默认的8000端口上运行Seahub, 而是想自定义端口（比如8001）中运行，请按以下步骤操作:

* 关闭Seafile服务器

```bash
./seahub.sh stop # 停止Seafile进程
./seafile.sh stop # 停止Seahub
```

更改`zcloudfile/conf/ccnet.conf`文件中SERVICE\_URL 的值(假设你的 ip 或者域名时45.76.2.212), 如下 (从 5.0 版本开始，可以直接在管理员界面中设置。注意，如果同时在 Web 界面和配置文件中设置了这个值，以 Web 界面的配置为准。):

```bash
SERVICE_URL = http://45.76.2.212:8001
```

* 重启Seafile服务器

```bash
./seafile.sh start # 启动Seafile服务
./seahub.sh start 8001 # 启动Seahub网站 （运行在8001端口上）
```

## 关闭/重启Seafile和Seahub

* 关闭

```bash
./seahub.sh stop # 停止Seahub
./seafile.sh stop # 停止Seafile进程
```

* 重启

```bash
./seafile.sh restart # 停止当前的Seafile进程，然后重启Seafile
./seahub.sh restart  # 停止当前的Seahub进程，并在8000端口重新启动Seahub
```

* 如果停止/重启的脚本运行失败 大多数情况下`seafile.sh` `seahub.sh`脚本可以正常工作。如果遇到问题：

  使用pgrep命令检查 seafile/seahub 进程是否还在运行中:

  ```bash
  pgrep -f seafile-controller # 查看Seafile进程
  pgrep -f "seahub" # 查看Seahub进程
  ```

  使用pkill命令杀掉相关进程

  ```bash
  pkill -f seafile-controller # 结束Seafile进程
  pkill -f "seahub" # 结束Seafile进程
  ```

## Nginx 环境下部署 Seahub/SeafServer

Seahub 是 Seafile 服务器的网站界面. SeafServer 用来处理浏览器端文件的上传与下载. 默认情况下, 它在 8082 端口上监听 HTTPS 请求. 这里我们通过反向代理（Reverse Proxy）部署 SeafServer. 我们假设你已经将 Seahub 绑定了域名"[www.zcloud.group"。](http://www.zcloud.group"。)

下面是一个 Nginx 配置文件的例子，

> Ubuntu

* 创建文件 /etc/nginx/site-available/seafile.conf，并拷贝以下内容
* 删除 /etc/nginx/site-enabled/default: rm /etc/nginx/site-enabled/default
* 创建符号链接: ln -s /etc/nginx/sites-available/seafile.conf /etc/nginx/sites-enabled/seafile.conf

```bash
server {
    listen 80;
    server_name seafile.example.com;
    rewrite ^ https://$http_host$request_uri? permanent;    # 强制将http重定向到https
    server_tokens off;
}
server {
    listen 443;
    ssl on;
    ssl_certificate /etc/nginx/ssl/www.zcloud.group.crt;
    ssl_certificate_key /etc/nginx/ssl/www.zcloud.group.key;
    server_name seafile.example.com;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:5m;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /etc/nginx/dhparam.pem;

    # secure settings (A+ at SSL Labs ssltest at time of writing)
    # see https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    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_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 https;

        access_log      /var/log/nginx/seahub.access.log;
        error_log       /var/log/nginx/seahub.error.log;

        proxy_read_timeout  1200s;

        client_max_body_size 0;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        client_max_body_size 0;

        proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_send_timeout  36000s;
        proxy_request_buffering off;

        send_timeout  36000s;
    }

    location /media {
        root /home/zcloud/seafile-server-latest/seahub;
    }
}
```

## 修改 SERVICE\_URL 和 FILE\_SERVER\_ROOT

下面还需要更新SERVICE\_URL和FILE\_SERVER\_ROOT这两个配置项。否则无法通过Web正常的上传和下载文件。 5.0 版本开始，您可以直接通过管理员Web界面来设置这两个值 (注意，如果同时在Web界面和配置文件中设置了这个值，以Web 面的配置为准。)：

5.0 版本之前需要修改 ccnet.conf 文件和 seahub\_settings.py 文件

* 修改 ccnet.conf `SERVICE_URL = https://www.zcloud.group`
* 修改 seahub\_settings.py `FILE_SERVER_ROOT = 'https://www.zcloud.group/seafhttp'`

```bash
# to generate your dhparam.pem file, run in the terminal
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
```

## 通过OpenSSL生成SSL数字认证

使用HTTP（超文本传输）协议访问互联网上的数据是没有经过加密的。也就是说，任何人都可以通过适当的工具拦截或者监听到在网络上传输的数据流。但是有时候，我们需要在网络上传输一些安全性或者私秘性的数据，譬如：包含信用卡及商品信息的电子订单。这个时候，如果仍然使用HTTP协议，势必会面临非常大的风险！相信没有人能接受自己的信用卡号在互联网上裸奔。

HTTPS（超文本传输安全）协议无疑可以有效的解决这一问题。所谓HTTPS，其实就是HTTP和SSL/TLS的组合，用以提供加密通讯及对网络服务器的身份鉴定。HTTPS的主要思想是在不安全的网络上创建一安全信道，防止黑客的窃听和攻击。

SSL（安全套接层）可以用来对Web服务器和客户端之间的数据流进行加密。

SSL利用非对称密码技术进行数据加密。加密过程中使用到两个秘钥：一个公钥和一个与之对应的私钥。使用公钥加密的数据，只能用与之对应的私钥解密；而使用私钥加密的数据，也只能用与之对应的公钥解密。因此，如果在网络上传输的消息或数据流是被服务器的私钥加密的，则只能使用与其对应的公钥解密，从而可以保证客户端与与服务器之间的数据安全。

### 数字证书(Certificate)

在HTTPS的传输过程中，有一个非常关键的角色——数字证书，那什么是数字证书？又有什么作用呢？

所谓数字证书，是一种用于电脑的身份识别机制。由数字证书颁发机构（CA）对使用私钥创建的签名请求文件做的签名（盖章），表示CA结构对证书持有者的认可。数字证书拥有以下几个优点：

* 使用数字证书能够提高用户的可信度
* 数字证书中的公钥，能够与服务端的私钥配对使用，实现数据传输过程中的加密和解密
* 在证认使用者身份期间，使用者的敏感个人数据并不会被传输至证书持有者的网络系统上

X.509证书包含三个文件：key，csr，crt。

* key是服务器上的私钥文件，用于对发送给客户端数据的加密，以及对从客户端接收到数据的解密
* csr是证书签名请求文件，用于提交给证书颁发机构（CA）对证书签名
* crt是由证书颁发机构（CA）签名后的证书，或者是开发者自签名的证书，包含证书持有人的信息，持有人的公钥，以及签署者的签名等信息

> 在密码学中，X.509是一个标准，规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。

### 创建自签名证书的步骤

1. **生成私钥** 使用openssl工具生成一个RSA私钥 `openssl genrsa -des3 -out server.key 2048` 说明：生成rsa私钥，des3算法，2048位强度，server.key是秘钥文件名。生成私钥，需要提供一个至少4位的密码。
2. **生成CSR(证书签名请求)** 生成私钥之后，便可以创建csr文件了。 此时可以有两种选择。理想情况下，可以将证书发送给证书颁发机构（CA），CA验证过请求者的身份之后，会出具签名证书（很贵）。另外，如果只是内部或者测试需求，也可以使用OpenSSL实现自签名，具体操作如下： `openssl req -new -key server.key -out server.csr` 说明：需要依次输入国家，地区，城市，组织，组织单位，Common Name和Email。其中Common Name，可以写自己的名字或者域名，如果要支持https，Common Name应该与域名保持一致，否则会引起浏览器警告。

```bash
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Shanghai
Locality Name (eg, city) []:Shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TW
Organizational Unit Name (eg, section) []:test
Common Name (e.g. server FQDN or YOUR name) []:www.zcloud.group
Email Address []:zhaojunhhu@gmail.com
```

3. **删除私钥中的密码** 在第1步创建私钥的过程中，由于必须要指定一个密码。而这个密码会带来一个副作用，那就是在每次启动Web服务器时，都会要求输入密码，这显然非常不方便。要删除私钥中的密码，操作如下：

```bash
mv server.key server.origin.key
openssl rsa -in server.origin.key -out server.key
```

4. **生成自签名证书** 如果你不想花钱让CA签名，或者只是测试SSL的具体实现。那么，现在便可以着手生成一个自签名的证书了。 需要注意的是，在使用自签名的临时证书时，浏览器会提示证书的颁发机构是未知的。

```bash
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```

说明：crt上有证书持有人的信息，持有人的公钥，以及签署者的签名等信息。当用户安装了证书之后，便意味着信任了这份证书，同时拥有了其中的公钥。证书上会说明用途，例如服务器认证，客户端认证，或者签署其他证书。当系统收到一份新的证书的时候，证书会说明，是由谁签署的。如果这个签署者确实可以签署其他证书，并且收到证书上的签名和签署者的公钥可以对上的时候，系统就自动信任新的证书。
