用Raspberry Pi搭建NAS服务

为何要自建云服务或者NAS不是本文的重点,这里就不说明了。

本文重点在于提供一种价格低廉的自建云服务解决方案,并且易于学习和再现。

但是,讲述如何使用Linux系统以及一些基础的命令亦不是本文范围。

所以,开始阅读前,请先确认

本文的适合对象

  1. 我假设你有使用过Linux操作系统的经验;假设你知道什么是sudo、ls、以及文件系统
  2. 我亦假设你知道什么是RAID、SSH、http/https服务
  3. 如果要安装NextCloud,你还必须了解php、编译、mysql的相关知识

写在前面

自从打算着手自建云服务以来,一直在考虑实现方案。

成本是首要考虑的因素。毕竟如果自购硬件成本大于租用CVM,那为什么不去租一台?其次,如果不考虑成本,也完全可以直接采购现成的解决方案,没必要自己折腾了。
性能是其次的,毕竟是家用,不会有2位数的在线人数。
于是便有了这个方案。

采购准备

在开始组建软件前,你首先得准备一些必须的硬件。这里有一个清单可以对照着看。
清单里的设备并不都是需要新购的,你完全可以利用现有的设备。

清单

  • 一套 Raspberry Pi 3 Model B+(主板、外壳、电源)(约240元)
  • 一根HDMI链接线(约10元)
  • 一张16G或以上的Micro SD卡(约30元)
  • Micro SD卡读卡器
  • 一台支持HDMI的显示器
  • USB鼠标
  • 一台用于远程连接Raspberry Pi的电脑,或者USB键盘
  • 一个双盘位硬盘盒
  • 两块相同容量的硬盘
  • 建议使用有线网线连接网络(约10元)

Raspberry Pi

Raspberry Pi是一款使用ARM芯片的单片机,3B+是他们现在最新的型号。

这是一台完整的电脑,功能非常强大。3B+使用一款1.4GH的4核64位ARM CPU,1G内存,4个USB 2.0接口,一个HDMI显示接口,以及GPIO接口。

更重要的是,其功耗不到15瓦,售价约只有240元左右,作为一般家用的云服务主机简直完美。

如果你想要更多信息,点击这里访问他们的官网

如果你只相信官方指定经销商,这里是一个官方列表

外壳看起来不是必须的,但建议一定要买,一个坚固的外壳将给24小时运行的主板提供最基础的物理防护。

Micro SD卡

Raspberry Pi不含内置硬盘,采用外插SD卡作为存储。所以如果你没有用剩下的SD卡,可能就需要购买一张。

官方也提供已经预先录入NOOBS的卡卖,但是这价格完全不值得——那其实就是从官网下载了NOOBS,然后直接复制到卡里而已。

如果你打算新购一张SD卡,建议买读写速度快的——越快越好,毕竟这是整个系统中速度最慢的组件。

Micro SD卡读卡器

这当然是为了读写SD卡准备的,当然你手头很可能已经有很多个了,又或者你的电脑本来就能直接读取SD卡。即便新买一个,价格也便宜到忽略不计。

显示器

我相信看到本文的家里至少有一台显示器或者带显示器的笔记本,如果没有,好吧,你可以检查一下自己的电视机是否支持HDMI,支持的话也能拿来用,不然的话还是去买一台吧。

USB键盘

如果打算之后用NOOBS方式安装系统,并且你有一台笔记本或电脑用来远程连接Raspberry Pi,那么USB键盘就不是必须的,否则的话就去准备一个。

USB鼠标

事实上USB鼠标也不是必须的,前提是你有一个USB键盘。

双盘位硬盘座/硬盘柜

最后需要一个2盘位的硬盘盒用来接入大容量硬盘作为主要存储。
建议2盘位是为了成本考虑,淘宝上看了一圈,4盘位的都在400元以上,虽然用3个盘组RAID5很诱人(速度优于2块硬盘的RAID1),但这不是必须的,2盘位的性能够用,也位数据提供了坚实的保障。

最终我购买了一款Acasis的DS-P2U3C硬盘盒,这大约是我能找到的性价比最高的金属外壳硬盘盒,大约130元。如果你不在乎金属外壳,还有更便宜的选择。但请仔细挑选硬盘盒,不要选用那些不带外部供电的产品。

值得注意的是,Acasis还有一款双硬盘自带阵列的硬盘盒,价格非常诱人,但这是一笔没有必要的开销,而且不便以后扩展。我们将以软件实现阵列功能。

不得不说的是,硬盘柜是略优于硬盘底座的一个选择,原因当然是硬盘柜的外壳提供了基础的物理防护。之所以说略优,是因为硬盘本身是有外壳的,并不像电路板那样怕粉尘,但是如果你害怕自己的硬盘会受物理冲击,还是选择一款硬盘柜的好,当然相比底座价格更贵。

硬盘

最后,硬盘可以使用老设备上淘汰下来的。我就拆了两块2.5寸移动硬盘,它们正好都是500G大小。如果没有现成的硬盘,你就得去买两块,容量大小跟你的钱包商量。从目前市场行情看,3TB的3.5寸硬盘是最具性价比的。你也可以购买SSD硬盘,要提醒的是,速度超过网络或者USB 2.0的硬盘在目前的方案上不会带来任何性能提升。

[图片上传失败...(image-8beea1-1557927673898)]

[图片上传失败...(image-5a6c11-1557927673898)]

开始安装

为树莓派安装操作系统

你的树莓派已经到手,外壳也组装完毕,让我们马上为它安装操作系统。

NOOBS或者NOOBS

针对这次的需求,如果你对Linux比较熟悉,可以从官网下载安装Raspbian Stretch Lite。Lite版提供了最少的预装软件,并且不包含图形界面;这让你可以按需只安装必要的软件,减少空间浪费,提升服务器性能。

但是NOOBS方式安装起来更方便易懂,这正是本文的目标。所以我会提供NOOBS的安装说明。

制作安装盘

首先将你的SD卡格式化,注意使用FAT32格式,因为Pi在启动时只能识别FAT32文件系统。

然后从官网下载NOOBS文件,如果你的网络受限,也可以使用这个链接:百度网盘 提取码: yawk
目前版本是3.0.1,这个链接会有效至下一个版本发布。

NOOBS下载下来是一个zip文件,你只需将内容全部解压到你的SD卡,安装盘这就算准备好了,没错,丝毫不用怀疑。

安装系统

将制作好的SD卡插入树莓派,顺便接上鼠标,还有显示器,然后开机。

你面临的第一个选择是安装哪种系统,请选择Raspbian——官方系统。然后跟着向导一步步选下去就能完成安装过程,重新启动后会进入初始化设置。

设置界面中只有最后一步值得注意,系统会询问是否需要更新软件,如果你能够接入wifi或者网线,就请更新,否则话就跳过,之后我们还是能通过控制台更新。

系统设置

现在我们要为之后的作业做一些基本设置,包括打开远程SSH连接和系统优化。

在开始设置前,如果你还没有连上网络,或之前更新软件失败。现在请立即更新。

打开终端——你能在屏幕最上方的任务栏上找到它,然后依次输入以下命令:

sudo apt-get update
sudo apt-get upgrade

update命令更新软件源索引,upgrade命令将更新所有需要升级的软件。
过程中请留意控制台输出,如果有下载失败可以多试几次。

设置启动到命令行

更新完毕后我们开始配置系统。
在控制台输入这条命令:

sudo raspi-config

然后在出现的界面中选择:

3 Boot Options

然后在第二级菜单中选择:

B1 Desktop / CLI

最后选择:

B1 Console

这条设置树莓派每次启动后直接进入命令行,而不是图形桌面,之后的软件安装配置大多只能通过命令行进行,所以我们用不上图形桌面。

开启SSH登录

从一级菜单,选择:

5 Interfacing Options

然后选择

P2 SSH

打开了SSH后,下次启动时我们就能通过SSH远程连接树莓派了。

重新划分系统内存

从一级菜单中选

7 Advanced Options

然后

A3 Memory Split

树莓派的显卡是共享系统内存,我们因为无需使用图形界面,所以这里输入8。只要分配8M给显卡就足够了,剩下的都能用于系统运行。

必要的设置到此完毕,记得重启生效。

组建磁盘阵列

对于需要长时间运行的服务,组建RAID1阵列我认为是必须的。要注意消费级硬盘的可靠性测试都不是基于24小时运行而设计的,即便购买了企业级硬盘,也没有厂商敢保证他们的硬盘可以抗打雷抗停电——事实上即便是企业内部服务器购买了企业级硬盘,仍然会组建磁盘阵列来保持数据的安全。说到底,这取决于硬盘里的数据对你到底有多重要。

安装mdadm

警告
组建RAID1过程中,会将两块硬盘都格式化。所以在开始前,请确保两块硬盘中没有任何有用的数据。
{: .notice--danger}

远程连接到你的树莓派,执行以下命令安装mdadm:

sudo apt-get install mdadm

小贴士
试试

sudo apt-get install mdadm -y

这样就不用回答『您希望继续执行吗?』这样的问题了。
{: .notice--info}

确认两块硬盘的设备名称

执行lsblk命令确认硬盘设备名称

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda           8:0    0 465.8G  0 disk
...
sdb           8:16   0 465.8G  0 disk
...
mmcblk0     179:0    0  29.8G  0 disk
├─mmcblk0p1 179:1    0   1.8G  0 part
├─mmcblk0p2 179:2    0     1K  0 part
├─mmcblk0p5 179:5    0    32M  0 part
├─mmcblk0p6 179:6    0    66M  0 part  /boot
└─mmcblk0p7 179:7    0  27.9G  0 part  /

可以看到例子中存在3块disk。
其中mmcblk0是Micro SD卡,sda与sdb则是两块硬盘。

创建阵列磁盘md0

使用sda与sdb两块硬盘创建新的RAID1硬盘md0

sudo mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/sda /dev/sdb

--create /dev/md0 表示新建的设备名称为/dev/md0
--level=mirror 表示RAID类型为RAID1,即『镜像』
--raid-devices=2 表示新RAID盘包含两个设备
最后跟上设备名称就回车执行。

然后控制台会输出以下内容:

mdadm: Note: this array has metadata at the start and
    may not be suitable as a boot device.  If you plan to
    store '/boot' on this device please ensure that
    your boot-loader understands md/v1.x metadata, or use
    --metadata=0.90
Continue creating array? 

这个提示的大意是,正要创建的阵列不支持作为启动分区使用,确认是否继续;我们当然要输入y,并回车继续。

最后如果看到以下信息,就说明md0创建已经成功:

mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

然后确认下新建的md0的运行状态:

# pi @ raspberrypi in ~/tmp [11:45:20] C:2
$ sudo mdadm --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Thu May  9 15:14:20 2019
     Raid Level : raid1
     Array Size : 488255488 (465.64 GiB 499.97 GB)
  Used Dev Size : 488255488 (465.64 GiB 499.97 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

  Intent Bitmap : Internal

    Update Time : Wed May 15 02:04:02 2019
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           Name : raspberrypi:0  (local to host raspberrypi)
           UUID : 296a305d:809bf8cd:c259df5a:70488bf7
         Events : 15549

    Number   Major   Minor   RaidDevice State
       0       8        0        0      active sync   /dev/sda
       1       8       16        1      active sync   /dev/sdb

没有异常,很好,创建成功。

最后不要忘记将md0的信息更新到mdadm.cconf文件,这样每次开机启动时候mdadm都会自动登记md0设备。

sudo mdadm --detail --scan --verbose >> /etc/mdadm/mdadm.conf

这条命令会扫描系统上所有已经创建的RAID设备,并将其信息输出成mdadm.conf能够识别的格式,最终保存到/etc/mdadm/mdadm.conf文件的末尾

mdadm的功能很强大,包括对raid盘的监控、扩展等等。
想要学习其更高级的使用方法的话,可以查看其man资料。

格式化

在这之前先格式化一下,为md0创建文件系统:

sudo mkfs.ext4 /dev/md0

挂载

阵列磁盘已经就绪,让我们挂上它,立即开始使用!

先创建想要挂载的位置

sudo mkdir /mnt/data

然后挂载

sudo mount /dev/md0 /mnt/data

这个例子将md0盘挂到了/mnt/data目录中,实际你可以挂载到自己喜欢的位置,例如:~/data,挂载前别忘了先创建该目录就行。

好吧,现在开始终于可以通过/mnt/data目录写我们的RAID盘了。
但是,等下,别急,如果你不想每次重启机器都自己手动挂载,那我们还有最后一步,那就是开机自动挂载。

开机自动挂载

linux的磁盘挂载信息都记录在/etc/fstab文件里
使用你拿手的文本编辑器打开它,本文所有例子将使用nano。

sudo nano /etc/fstab

在文件的最后插入一行:

/dev/md0 /mnt/data ext4 defaults 0 0

如果乐意,你可以加上一行「#」开头的注释,这有助于你日后回忆。

Tips
nano中按ctrl+o保存,ctrl+x退出。请留意底部的快捷键功能提示
{: notice--info}

至此,一台挂载了RAID1硬盘的服务器已经准备完毕。
即使不继续安装任何其他软件,你也已经可以将这台机器当做一台可靠的重要数据备份机使用。可我们当然不会满足于此,对吧?

下一节开始将为树莓派逐步安装配置各类软件来为我们更好的服务。

服务 服务 服务!

终于要开始安装我们的云服务,这才是我们真正的目标,之前的都是准备工作。

但是到了云服务这块,可选择的内容非常之多。接下来要做的内容并不全都是必须的,可以根据自己的需要选择性部署。

syncthing

syncthing是一个非常有意思的软件,其主要用途是用来在各个计算机设备间进行文件同步。这『计算机设备』包含很多不同的操作系统甚至是cpu架构——同样包括手机。

但是要注意syncthing目前并没有ios版本
这意味着你不能通过苹果手机与自己的服务器进行同步。
如果你想用苹果手机进行云同步,那么可以跳过这一节,试试之后的NextCloud。

syncthing的原理是通过类似电驴的p2p协议进行通讯传输。这种协议不需要使用中央服务器来保存数据并负责分发,而是由A机器直接路由到B机器来进行通讯。

synthing并不需要知道需要通讯的机器都ip地址,它采用中介服务器方式,登记连上来的机器的网络信息,负责为需要通讯的双法寻找路由握手。所以synthing不需要通讯双方都具备公网ip,只要他们能联通到同一个网络,互相之间就能通讯。

当然,假设AB两台机器都没有公网ip,要让他们之间能通讯,肯定是需要经过至少一台具备公网ip的机器的,这种在通讯双方间作为桥梁性质的机器称作中介服务器,发挥着路由的作用。

所以你在两台机器间同步数据的时候,你的数据可能会经过1台或者多台中介,最终保存到你指定的计算机上。

但是不用担心数据安全的问题,中介服务器实际并不知道自己接收到的数据将要传输的最终目的地是哪里,下一个接手的可能是目的地,更多可能是另一台中介。另外syncthing的数据在传输时都使用了TLS进行加密。

综上,syncthing是用来作为同步和备份网盘的极好方案。

想要了解syncthing更多,点击这里访问syncthing官网。

Raspberry Pi上的安装

在Raspberry Pi上安装syncthing的一个比较简单的方式是——直接下载。

你可以从官网找到ARM版的安装包。
如果你的网络受到神秘力量的干扰而无法访问官网,可以转为访问项目组的github release主页
这两个地方哪里下载都是一样的。

要注意的是,为了服务器稳定,请下载最新的release版本,而不是rc候选版本。并且能够在Raspberry Pi上运行的是arm版,而不是arm64.

在Raspberry Pi上可以使用wget命令进行文件下载:

wget https://github.com/syncthing/syncthing/releases/download/v1.1.3/syncthing-linux-arm-v1.1.3.tar.gz

下载到你喜欢的地方,然后解压:

tar -xzvf syncthing-linux-arm-v1.1.3.tar.gz

然后直接执行syncthing:

syncthing-linux-arm-v1.1.3/syncthing

注意控制台的输出信息,待启动彻底完成后按下键盘的Ctrl+C以中指syncthing。

这是因为syncthing第一次启动默认配置的web管理地址只能从本机(树莓派)上访问,而本机现在只是一个控制台。

开启远程访问

接着找到syncthing的配置文件,我们要修改它能在局域网其他地方也能访问。
syncthing的配置文件默认放在 ~/.config/syncthing目录下。

使用nano打开配置文件:

nano ~/.config/syncthing/config.xml

找到这段内容:

    <gui enabled="true" tls="false" debugging="false">
        <address>127.0.0.1:8384</address>

将127.0.0.1改成0.0.0.0
改完后看起来这样:

    <gui enabled="true" tls="false" debugging="false">
        <address>0.0.0.0:8384</address>

保存后再次启动syncthing,启动成功后你就可以通过https://ip:8384/ 来访问你的syncthing管理页面了。
其中ip是Raspberry Pi的ip地址。

你可以通过ifconfig命令来查看:

sudo ifconfig -a

或者从你的路由器管理页面上找到。

同步文件夹设置

事实上syncthing的官方文档维护的不错,如果你的网络不受神秘力量影响,可以直接查看官方文档进行你的同步文件夹设置。

如果不幸你访问不了官方文档,那么还有个好消息是syncthing的全中文界面异常完整,设置非常简单。
强烈建议你先点击『添加文件夹』按钮试试。
[图片上传失败...(image-a75aa5-1557927673898)]
[图片上传失败...(image-8639ed-1557927673898)]
[图片上传失败...(image-475aac-1557927673898)]
在高级选项卡里可以设置文件类型——发送与接收、仅发送、仅接收。

这是非常有用的一个功能,这意味着你不仅可以建同步目录,也可以建备份目录。

Android手机安装syncthing

如果前面你仔细看了,当然知道syncthing没有ios版本。

但坏消息不止这一个——syncthing的安卓下载放在注明的Google Play商店里。这是个没有些特殊手段永远都到达不了地方,是吗?(笑)

如果你有自己的神通,那是时候显现了。
如果你没有神通,我提供一个百度网盘 提取码: x4jj。
这个是由F-Droid编译并签名,且保证与开源源码一致的版本。
连接里当然也提供了F-Droid的签名,请自行验证。

安卓版syncthing的界面与服务器几乎一致(请使用网页管理页面,原生界面设置功能比网页管理页面少)

手机上唯一要多做一步的就是添加设备,把你的Raspberry Pi上的syncthing添加进来,它们旧能同步了。

打开Raspberry Pi上的syncthing的管理页面,点击显示设备ID,会出现一个二维码;然后在手机上用相机扫一下二维码,将得到的ID复制下来;然后在安卓syncthing上点击添加设备,将复制下来的ID粘贴进去,就能方便的设置成功。

然后你就可以在安卓上设置需要同步的文件夹推送给Raspberry Pi,或者接收Raspberry Pi要推送给安卓的文件夹。

关于公网IP

接着会介绍一些web服务的自建方法。这些web服务,如果你想在外网也能随时随地访问的话,至少需要一个公网IP,哪怕是动态的。
如果不幸你跟我一样处在可以上外网却没有公网IP的情况(ISP劫持了DNS,隐藏了真实的外网IP,并封锁所有端口),那么也不要太过气馁,我至少还有两个办法可以让你穿透出去。

花生壳

花生壳是国内的老牌内网穿透服务商了。
官网连接
现在买花生棒还送每月2G流量的服务。
我并不是要在这里推销花生棒或者花生壳。相反,他们的服务非常不具性价比。

首先,所谓的花生棒就是一台装了内网端口映射工具的低性能单片机,而内网端口映射实际上只要装一个软件就行,所以这100来块钱实际就是用来买每月1G流量的(它们的免费软件账号有1G流量)。

其次,每月2G流量是什么概念?用来传文件不太合适,记记笔记是够用的。
最危险的,免费账号只支持80端口,这是什么概念?意思是你的所有连接只能从http进出,而不是https,这等于所有数据都裸露在通讯路径上,不仅未授权的人可以随便截取,花生壳的员工也只要简单的把文件保存下来直接就能看。

那还不如百度网盘?这是肯定的。

花生壳的确有https服务,但是,但是,SSL加密证书得买它们的,价格呢?都够我去租一台CVM了。

Sunny

Sunny ngrok
这并不是ngrok的官网,而是用ngrok的1.x开源软件改造后面向国内运营的网站。10元/月/端口,限速5M带宽,对于私用是很实惠的。
要注意的是,一定要选择使用https协议,只有这个才是加密的。

安装nginx

上节介绍的syncthing是本文中唯一一个不需要公网ip的服务。
说到底,syncthing通过中介服务器进行数据交换,而不是基于web服务。

在接下来的内容中要配置的几乎都是web服务,我打算把它们都架设在nginx上。

非常幸运的是,apt-get源里提供了nginx的安装包,这意味着你只要执行apt-get就能完成安装:

sudo apt-get install nginx-full -y

然后通过systemctl配置nginx服务作为系统服务开机自启:

sudo systemctl enable nginx

如果没有什么出错信息,那么nginx就算装成功了。

nginx的配置不在本节内讲,这是根据你需要运行什么服务决定如何添加配置,如果不需要安装任何web服务,nginx都不需要安装。

NextCloud

官网在这里
NextCloud算是老牌的开源云盘了,它并不是一个同步工具,而是类似DropBox的云盘。虽然也支持文件夹自动上传,但是对比syncthing就弱了太多。

好消息是,NextCloud支持所有手机端。
[图片上传失败...(image-f399cb-1557927673898)]

安卓版官网直接能够下载!
点『App Store』下面那个『...direct AAPK download...』就行。

Raspberry Pi安装NextCloud服务器端

坏消息是,NextCloud对于缺少Linux服务器经验的人来说过于复杂了。

因为NextCloud是用PHP开发的,所以除了nginx,还需要安装PHP。

然后NextCloud需要使用数据库,好吧,我推荐安装MySQL。

一步步来。

安装PHP7.3

更坏的消息是,NextCloud 16.0需要运行在PHP 7.1以上,而apt-get官方源的版本是7.0

所以我们只能自己编译安装PHP7.3。

好消息是你看到了本文,按照步骤一步步做下去就能成功。

先为编译安装一些必要的依赖包:

sudo apt-get install autoconf build-essential curl libtool \
  libssl-dev libcurl4-openssl-dev libxml2-dev libreadline7 \
  libreadline-dev libzip-dev libzip4 nginx openssl \
  pkg-config zlib1g-dev

准备好编译输出目录:

mkdir -p ~/bin/php7-latest/

官网下载php-7.3.5.tar.gz源码包:

wget https://www.php.net/distributions/php-7.3.5.tar.gz

解压:

tar -xzvf php-7.3.5.tar.gz

配置编译参数:

./configure --prefix=$HOME/bin/php-latest \
    --enable-mysqlnd \
    --with-pdo-mysql \
    --with-pdo-mysql=mysqlnd \
    --enable-bcmath \
    --enable-fpm \
    --with-fpm-user=www-data \
    --with-fpm-group=www-data \
    --enable-mbstring \
    --enable-shmop \
    --enable-sockets \
    --enable-sysvmsg \
    --enable-sysvsem \
    --enable-sysvshm \
    --enable-zip \
    --with-zlib \
    --with-curl \
    --with-pear \
    --with-openssl \
    --enable-pcntl \
    --with-readline \
    --with-gd

注意控制台输出,没有出错信息才算成功。

编译:

make

注意控制台输出,没有出错信息才算成功。

安装:

make install

如果一切顺利,所有可执行文件都会编译到~/bin/php7-latest/ 目录下。

然后将php的执行目录加入系统PATH环境变量。
如果用的是bash,请编辑/.bashrc;如果是zsh,编辑/.zshrc,在文件最后加入这句:

export PATH=$HOME/bin/php-latest/bin:$HOME/bin/php-latest/sbin:$PATH

用source命令使刚才的更改生效:

source ~/.bashrc

或者

source ~/.zshrc

配置php-fpm作为系统服务。
这一步有很多做法,可以写initd脚本,也可以写systemd配置,也可以使用supervisor进行管理。
这里提供一个可以运行的initd脚本:

#! /bin/sh

### BEGIN INIT INFO
# Provides:          php-fpm
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php-fpm
# Description:       starts the PHP FastCGI Process Manager daemon
### END INIT INFO

prefix=/home/pi/bin/php-latest
exec_prefix=${prefix}

php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm.conf
php_fpm_PID=${prefix}/var/run/php-fpm.pid


php_opts="--fpm-config $php_fpm_CONF --pid $php_fpm_PID"


wait_for_pid () {
    try=0

    while test $try -lt 35 ; do

        case "$1" in
            'created')
            if [ -f "$2" ] ; then
                try=''
                break
            fi
            ;;

            'removed')
            if [ ! -f "$2" ] ; then
                try=''
                break
            fi
            ;;
        esac

        echo -n .
        try=`expr $try + 1`
        sleep 1

    done

}

case "$1" in
    start)
        echo -n "Starting php-fpm "

        $php_fpm_BIN --daemonize $php_opts

        if [ "$?" != 0 ] ; then
            echo " failed"
            exit 1
        fi

        wait_for_pid created $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed"
            exit 1
        else
            echo " done"
        fi
    ;;

    stop)
        echo -n "Gracefully shutting down php-fpm "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -QUIT `cat $php_fpm_PID`

        wait_for_pid removed $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed. Use force-quit"
            exit 1
        else
            echo " done"
        fi
    ;;

    status)
        if [ ! -r $php_fpm_PID ] ; then
            echo "php-fpm is stopped"
            exit 0
        fi

        PID=`cat $php_fpm_PID`
        if ps -p $PID | grep -q $PID; then
            echo "php-fpm (pid $PID) is running..."
        else
            echo "php-fpm dead but pid file exists"
        fi
    ;;

    force-quit)
        echo -n "Terminating php-fpm "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -TERM `cat $php_fpm_PID`

        wait_for_pid removed $php_fpm_PID

        if [ -n "$try" ] ; then
            echo " failed"
            exit 1
        else
            echo " done"
        fi
    ;;

    restart)
        $0 stop
        $0 start
    ;;

    reload)

        echo -n "Reload service php-fpm "

        if [ ! -r $php_fpm_PID ] ; then
            echo "warning, no pid file found - php-fpm is not running ?"
            exit 1
        fi

        kill -USR2 `cat $php_fpm_PID`

        echo " done"
    ;;

    configtest)
        $php_fpm_BIN -t
    ;;

    *)
        echo "Usage: $0 {start|stop|force-quit|restart|reload|status|configtest}"
        exit 1
    ;;

esac

将上面这段脚本保存为/etc/init.d/php-fpm这个文件即可。

接着运行:

sudo systemctl enable php-fpm

安装MySQL

先更新一下源索引,保证安装到的是最新版:

sudo apt-get update

安装MySQL Server:

sudo apt-get install mysql-server

开启服务

sudo systemctl enable mysql

登入数据库:

mysql -u root -p

修改root用户密码以及允许远程登入:

use mysql;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的root账号密码' WITH GRANT OPTION;
flush privileges;

然后就可以在别的机器上用图形化客户端接入这个MySQL了。

下载并安装NextCloud Server

本文使用的是NextCloud Server 16.0.0.0
从官网下载压缩包并解压到/var/www/nextcloud 目录下。

改一下目录所有者,因为nginx默认使用www-data用户启动:

sudo chown -R www-data:www-data /var/www/nextcloud/

根据官方文档说明,使用occ命令安装:

$ cd /var/www/nextcloud/
$ sudo -u www-data php occ  maintenance:install --database
"mysql" --database-name "nextcloud"  --database-user "root" --database-pass
"password" --admin-user "admin" --admin-pass "password"
Nextcloud is not installed - only a limited number of commands are available
Nextcloud was successfully installed

注意控制台输出,如果发现自己什么参数错了的话,建议整个目录删掉重新来一遍。

配置nginx使用php解析nextcloud

终于到这一步。
先删除nginx的站点默认配置:

sudo rm /etc/nginx/sites-enabled/default

然后新建一个nextcloud文件。
文件名其实随便都可以,nginx启动时会读取这个目录下的所有文件。
nextcloud配置内容如下:

upstream php-handler {
    server 127.0.0.1:9000;
    #server unix:/var/run/php/php7.0-fpm.sock;
}

server {
    listen 80;
    listen [::]:80;
    server_name cloud.example.com;
    # enforce https
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name cloud.example.com;

    # Use Mozilla's guidelines for SSL/TLS settings
    # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    # NOTE: some settings below might be redundant
    ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
    ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Referrer-Policy no-referrer;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;

    # Path to the root of your installation
    root /var/www/nextcloud/;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;

    # The following rule is only needed for the Social app.
    # Uncomment it if you're planning to use this app.
    # rewrite ^/.well-known/webfinger /public.php?service=webfinger last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    location / {
        rewrite ^ /index.php$request_uri;
    }

    location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
        deny all;
    }
    location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
        fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff2?|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        add_header Referrer-Policy no-referrer;

        # Optional: Don't log access to assets
        access_log off;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$request_uri;
        # Optional: Don't log access to other assets
        access_log off;
    }
}

这个配置模板是从官方文档复制过来的,连接见本节最后。
注意将cloud.example.com替换成自己的域名或者ip地址。

    ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
    ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

这两句指定了SSL证书存放的位置,有证书的话请自行放置并修改。

接着记得重启下nginx:

sudo systemctl restart nginx

现在你应该能从 https://ip 或者域名打开nextcloud的网页版。
这个地址也是你的手机客户端连接服务器时的地址。

更多信息请参考官网文档,上面还有一个将nextcloud配置到子路径下的模板

安装安卓版nextcloud

这根本不值得写,只要从官网下载了apk装上就行。
启动后选择自建服务器,输入之前部署在Raspberry Pi上的url地址,根据向导一路下一步就行。

至此,自建NextCloud云盘终于炼成。

写在最后

是时候来计算下运营成本。
Raspberry Pi的功率为 5V x 2.5A = 12.5W
硬盘底座的功率为 12V x 3A = 36W
总计 48.5W
每天能耗 48.5W x 24H = 1164WH = 1.164千瓦时
如果每个字平均按0.5元算,一天电费0.582元,一个月不到18元。

事实上实际使用起来还要低一些,毕竟不是一直满功率运行——事实上大多时候可能都是在空转。

开始掌控自己的数据吧。
1.png
2.png
3.png
4.png
5.png
6.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容