Nas

绿联如何支持nfs server

Posted by Lengzhao Blog on May 19, 2024

NAS

个人对数据安全越来越关注。担心硬盘故障导致数据丢失。 所以我入坑了NAS。

平常使用的是mac mini,存储空间比较有限。所以NAS也需要承担扩展盘的工作。

我的需求比较低:扩展盘功能+家庭多媒体。群晖或许是更好的选择,但是价格不便宜。 从网上的资料上看,绿联私有云是支持NFS的。 所以,我买了一个绿联的私有云。结果就是入坑:不支持NFS,只能存储数据,无法作为扩展盘(samba/webDav只有rw权限,没有x权限)。

更具体的分析请查看别人的深度解析

绿联如何支持NFS

想法1:通过ssh进入后台,安装对应模块

  1. 通过开启“远程调控”功能,ssh进入后台。
  2. opkg install nfs-utils,最终失败了

想法2:docker启动nfs server

  1. 本身支持docker,尝试直接安装nfs server
  2. image: itsthenetwork/nfs-server-alpine
  3. 最后失败了,因为这些镜像依旧需要系统有nfsd等服务,但它被绿联阉割了

想法3:自己写个nfs server

  1. 结果:成功了,但又没完全成功
  2. 直接用golang写一个:github.com/willscott/go-nfs
  3. 代码如下:
package main

import (
	"fmt"
	"net"
	"os"
	"time"

	"github.com/go-git/go-billy/v5"
	"github.com/go-git/go-billy/v5/osfs"
	nfs "github.com/willscott/go-nfs"
	nfshelper "github.com/willscott/go-nfs/helpers"
)

func main() {
	listener, err := net.Listen("tcp", ":2049")
	if err != nil {
		fmt.Printf("Failed to listen: %v\n", err)
		return
	}
	fmt.Printf("osnfs server running at %s\n", listener.Addr())

	bfs := osfs.New("/nfsshare")
	bfsPlusChange := NewChangeOSFS(bfs)

	handler := nfshelper.NewNullAuthHandler(bfsPlusChange)
	cacheHelper := nfshelper.NewCachingHandler(handler, 1024)
	fmt.Printf("%v", nfs.Serve(listener, cacheHelper))
}

// NewChangeOSFS wraps billy osfs to add the change interface
func NewChangeOSFS(fs billy.Filesystem) billy.Filesystem {
	return COS{fs}
}

// COS or OSFS + Change wraps a billy.FS to not fail the `Change` interface.
type COS struct {
	billy.Filesystem
}

// Chmod changes mode
func (fs COS) Chmod(name string, mode os.FileMode) error {
	return os.Chmod(fs.Join(fs.Root(), name), mode)
}

// Lchown changes ownership
func (fs COS) Lchown(name string, uid, gid int) error {
	return os.Lchown(fs.Join(fs.Root(), name), uid, gid)
}

// Chown changes ownership
func (fs COS) Chown(name string, uid, gid int) error {
	return os.Chown(fs.Join(fs.Root(), name), uid, gid)
}

// Chtimes changes access time
func (fs COS) Chtimes(name string, atime time.Time, mtime time.Time) error {
	return os.Chtimes(fs.Join(fs.Root(), name), atime, mtime)
}
  1. 编译成可执行文件,并命名为nfsserver
  2. 将其制作成docker镜像
FROM alpine:latest
VOLUME /nfsshare
COPY nfsserver /home/
RUN chmod +x /home/nfsserver
EXPOSE 2049
RUN ls -l /home/
ENTRYPOINT ["/home/nfsserver"]
  1. 在docker操作界面上,创建容器
  2. 设置需要共享的目录,并将其挂载到容器中
  3. 映射端口2049:2049
  4. 启动镜像
  5. 默认的方式mount

     mount -o port=2049,mountport=2049 -t nfs 192.168.1.100:/ /Volumes/nfs
    
    1. 失败了,提示:mount_nfs: can’t mount with remote locks when server (192.168.1.100) is not running rpc.statd: RPC prog. not avail
    2. 发现缺少了portmapper,问题依旧是nfs-utils被阉割
    3. 所以需要换种方式
  6. 成功的方式
    1. 最后的mount命令如下,需要指定nolock,使用的时候,应该避免多人共用。
    2. 如果有多个人,可以每个人启动一个容器,映射不同端口,挂载不同目录。
mount -o port=2049,mountport=2049,proto=tcp,vers=3,nolock  -t nfs 192.168.1.100:/ /Volumes/nas
  1. 使用:
    1. 默认rwx功能可以,但是会遇到文件锁的相关问题
    2. 复现流程
    3. 在挂载的文件夹里面,创建一个golang项目,执行go mod init nfsserver
    4. 遇到如下错误:
    go: updating go.mod: Lock /Volumes/nas/dist/go.mod: no locks available
    
    1. 深入分析,是因为lookup “._.go.mod”,文件不存在。

想法4:使用sshfs

  1. 可以启动一个docker容器,支持sshd的
  2. 然后通过sshfs连接
  3. 这种方式,传输都需要加密,安全可靠。但如果传输的数据量比较大,电脑和NAS会比较消耗CPU

想法5:使用FUSE远程文件系统

  1. seaweedfs
  2. 因为不需要加密,所以速度会比sshfs快,CPU也低。

家庭影院搭建

  1. nastool: flik007/nastools-fixed:latest
  2. 字幕:allanpk716/chinesesubfinder:latest
  3. 多媒体服务器:emby/embyserver:latest
  4. 资源检索:linuxserver/jackett:latest
  5. 资源下载:linuxserver/qbittorrent:latest