使用Syncthing和FileRun搭建私人云盘

入手NAS之后,我一直使用NextCloud + IPv6远程管理其中的文件,以及同步备份手机和电脑的数据。由于在北京租房,所以NAS被放在了父母家,这就导致当想要下载一些大文件时,即使是直连,也需要等很久。因而打算设计一个新的架构,用来解决这个问题。

问题和诉求

目前的问题主要有3个:

  1. 使用IPv6 + DDNS远程访问NAS并不稳定,有时遇到IP变换,或者所在网络不支持IPv6,数据便无法访问。
  2. 虽然NAS上使用ZFS组了软RAID1,但毕竟两块硬盘是在同一台机器上,一旦机器损坏,可能丢失所有数据。
  3. 有时,我会通过终端直接下载或复制一些文件到NAS中,但NextCloud并不能立即识别那些文件,必须手动更新数据库。

基于以上问题,我明确了下面3个诉求:

  1. 我需要在本地也保留一份完整的数据。
  2. 文件管理程序必须能够自动识别新文件。
  3. 本地数据和NAS中的数据必须保持一致.

新方案

经过搜索,我发现有两款软件可以满足我的需求:

  • FileRun:基于LAMP架构的Web文件管理器,可实时显示文件变化
  • Syncthing:集群文件存储工具,可在多台机器上同步文件

安装部署

FileRun

与NextCloud一样,FileRun也是一个基于LAMP架构的项目,因此安装部署的步骤相似。不同之处在于,它不需要重新扫描,就可以立即识别新文件,这大大提高了文件管理的灵活性。

  1. 安装Apache、MySQL和PHP

    1
    2
    sudo apt update
    sudo apt install apache2 mariadb-server php libapache2-mod-php php-mysql php-mbstring php-zip php-curl php-gd php-ldap php-xml php-imagick
  2. 配置数据库,注意修改用户密码

    1
    2
    3
    4
    5
    6
    sudo mysql
    CREATE DATABASE filerun;
    CREATE USER 'filerun'@'localhost' IDENTIFIED BY 'YOUR-DB-PASSWORD';
    GRANT ALL ON filerun.* TO 'filerun'@'localhost';
    FLUSH PRIVILEGES;
    exit
  3. 配置PHP

    • 安装ionCube
      1
      2
      3
      4
      5
      6
      wget https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz
      sudo tar -xzf ioncube_loaders_lin_x86-64.tar.gz -C /usr/lib/php
      sudo vim /etc/php/7.4/apache2/conf.d/00-ioncube.ini
      <<<
      zend_extension = /usr/lib/php/ioncube/ioncube_loader_lin_7.4.so
      >>>
    • 创建基础配置
      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
      sudo vim /etc/php/7.4/apache2/conf.d/filerun.ini
      <<<
      expose_php = Off
      error_reporting = E_ALL & ~E_NOTICE
      display_errors = Off
      display_startup_errors = Off
      log_errors = On
      ignore_repeated_errors = Off
      allow_url_fopen = On
      allow_url_include = Off
      variables_order = "GPCS"
      allow_webdav_methods = On
      memory_limit = 128M
      max_execution_time = 300
      output_buffering = Off
      output_handler = ""
      zlib.output_compression = Off
      zlib.output_handler = ""
      safe_mode = Off
      register_globals = Off
      magic_quotes_gpc = Off
      upload_max_filesize = 20M
      post_max_size = 20M
      enable_dl = Off
      disable_functions = ""
      disable_classes = ""
      session.save_handler = files
      session.use_cookies = 1
      session.use_only_cookies = 1
      session.auto_start = 0
      session.cookie_lifetime = 0
      session.cookie_httponly = 1
      date.timezone = "UTC"
      >>>

      sudo systemctl restart apache2
  4. 配置Apache

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sudo vim /etc/apache2/sites-available/filerun.conf
    <<<
    <VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/filerun

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    >>>

    sudo a2ensite filerun.conf
    sudo systemctl restart apache2
    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
    openssl req -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out filerun.crt -keyout filerun.key
    sudo mv filerun.crt /etc/ssl/certs/
    sudo mv filerun.key /etc/ssl/private/

    sudo a2enmod rewrite headers env dir mime ssl
    sudo vim /etc/apache2/sites-available/filerun.conf
    <<<
    <IfModule mod_ssl.c>
    <VirtualHost _default_:443>
    ServerName nas.colorfulshark.net

    <IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
    </IfModule>

    DocumentRoot /var/www/filerun

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on

    SSLCertificateFile /etc/ssl/certs/filerun.crt
    SSLCertificateKeyFile /etc/ssl/private/filerun.key

    <FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory /usr/lib/cgi-bin>
    SSLOptions +StdEnvVars
    </Directory>
    </VirtualHost>
    </IfModule>
    >>>

    sudo a2ensite filerun.conf
    sudo systemctl restart apache2
  5. 安装FileRun

    1
    2
    3
    4
    5
    cd /var/www
    sudo mkdir filerun && cd filerun
    sudo wget -O FileRun.zip https://filerun.com/download-latest-ubuntu-20
    sudo unzip FileRun.zip
    sudo chown -R www-data:www-data /var/www/filerun
  6. 配置FileRun

    在浏览器中打开http://IP(http)或者https://IP(https),即可打开FileRun的配置向导,在页面中完成配置即可。

Syncthing

Syncthing的功能非常简单:在两台机器之间同步目录。但同时,它又是目前我所知道的最强大的同步工具。

当我们想要在两台机器上同步数据时,往往最麻烦的地方不是如何配置同步策略,减少冲突,而是如何让两台机器连通。如果是局域网,我们可能只需要手动设置IP;但到了广域网,想要连通两台机器通常是非常困难的,往往需要一台具备公网IP的中转服务器作为桥梁。而Syncthing则如魔法般,把上面所说的步骤全部抹除了,两台机器在弹指一挥间,就自动完成了连接,无论它们身处何方。

那么Syncthing是如何做到的呢?这其实得益于它强大的网络探测功能。根据两台设备之间连接方式的不同,Syncthing会做如下处理:

  • 局域网:自动探测对方设备,IP互换,完成连接,此时不需要设备连接互联网。
  • 互联网:
    • 具备公网IP:只要任意一台机器具备且22000端口开放,两台机器将使用公网IP直连。
    • NAT网络:尝试使用UDP进行打洞,实现内网穿透,任意一台机器穿透成功,即可直连。
    • 以上方案均失败:使用Relay桥接服务器,这些服务器通常是公用的,因此速度较慢。

目前国内的运营商大多不再提供公网IPv4地址,取而代之的是公网IPv6地址。经过测试,使用IPv6并且开放22000端口后,是可以顺利连接的。

即使没有IPv6,Syncthing也会尝试UDP打洞,经过测试,成功率还是非常高的,即使是公司的WiFi网络,也能成功实现公网直连。

  1. 配置Syncthing源

    1
    2
    sudo curl -o /usr/share/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg
    echo "deb [signed-by=/usr/share/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list
  2. 安装Syncthing

    1
    2
    sudo apt update
    sudo apt install syncthing
  3. 配置Syncthing

    由于FileRun是使用www-data账户运行的,因此我们也使用该账户运行Synching,从而避免文件权限的问题。同时,将其监听IP改为0.0.0.0,这样就可以通过局域网IP访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    sudo mkdir /var/www/.config
    sudo chown www-data:www-data /var/www/.config
    sudo systemctl enable syncthing@www-data
    sudo systemctl start syncthing@www-data

    vim /var/www/.config/syncthing/config.xml
    <<<
    <address>127.0.0.1:8384</address> => <address>0.0.0.0:8384</address>
    >>>

    然后就可以通过http://IP:8384访问Syncthing的管理页面了。

要用好Syncthing,需要深入理解它的同步逻辑。在Syncthing中,每一台机器对应一个Device ID,同步的最小单位是Folder,使用Folder ID标识,因此一个具体的Folder可以标定为[Device ID]:[Folder ID]

Syncthing会保证你的设备ID是独一无二的,要连接两台机器,需要各自添加对方的ID,只有一方添加ID是不会建立连接的,所以ID并不需要保密。

若要在2台设备之间同步目录,首先要建立设备间的连接,然后在两台设备上各自创建共享目录,并共享给对方。

创建共享目录时,可以参考以下建议,以达到比较好的效果:

  1. 启用Trash Can File Versioning:这可以防止文件在一台机器上被误删除后,其它机器也跟着删除。自动清理时间可以设置为30天。
  2. Ignore Patterns设置为.*:这可以忽略隐藏文件,因为这些文件通常是临时文件。
  3. Full Rescan Interval设置为0:这在安卓手机上非常实用,可以节约电量,因为手机在切换网络时,Syncthing会重启,而这会强制重新扫描。
  4. 启用Ignore Permissions:我们通常不太关心文件权限的变化,忽略它也可以降低同步频率。

最终效果

两台主同步设备拥有全部的文件,互为备份,而手机则选择性地与之同步,最终实现数据的异地防灾。

参考

FileRun Server Install Guides

How to install FileRun on Ubuntu 20

How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 20.04

Accessing via WebDAV

https://apt.syncthing.net/

Syncthing Getting Started