低成本构建属于自己的云工具

原文地址

本文介绍如何构造自己的私有云工具,其功能包括分享、全文检索在线编辑等功能

这里需要强调一点,我搭建下面的服务主要用于个人日常办公/学习使用,没有频繁下载大文件的需求,对流量需求并不大,所以我购买阿里云服务时流量是按量付费。应用场景满足所有开源工具的开源协议

Why

  1. 广告是互联网的灵魂,但我不想看广告

  2. 互联网没有隐私,那是因为我用的是别人的服务

  3. 通过构建服务温故知新,锻炼一下自己的实际操作能力

需求

需求 三方服务 开源工具选型 功能 内存消耗
博客 免费,但有广告 Hugo + eureka 静态 Web 50MB
搜索 谷歌 CSE 需要FQ yacy 开箱即用的 web 搜索引擎 500MB
笔记 Wiki VIP 一般一年100元以上 seafile 多端文件自动同步 + ES 搜索 + wiki + 在线 Word 编辑 4GB
文件存储 百度网盘不限速一年200元 filebrowser 浏览器访问与上传/下载文件 50MB

工具与原理

基础工具

  1. 闲置 PC + Ubuntu + Docker,闲置的计算资源 & 简洁的软件部署与服务隔离
  2. 阿里云 / 腾讯云域名服务,购买自己喜欢的域名
  3. Let’s Encrypt,域名 HTTPs 免费证书 & 通配符域名证书
  4. VPS(阿里云 ECS 或者 腾讯 VPS) + Nginx + FRP,外网流量转发

我的闲置笔记本 6 核 12 线程 32GB 内存,日常 12% CPU使用率和 24GB 内存占用,1min/5min/15min 的负载一般在 1.5;VPS 只作为流量转发(只有 Nginx 和 FRP 服务),对性能要求较低,我的 VPS 单核 512MB 内存,CPU 使用率一直在 5% 左右,1min/5min/15min 的负载一般在 0.2 以内

原理

  1. VPS 提供公网 IP,实现外网访问能力与流量转发

  2. Nginx 实现正向代理,转发 HTTPs 请求到内部 HTTP 服务

  3. FRP 实现网络隧道,打通 VPS 和闲置 PC 网络

成本

阿里云最便宜的突发型 ECS(CPU 基准为 20%,超过 20% 将消耗额外资源,流量按使用量付费,5 年费用在打折期间大概 500 元),使用阿里云 PTS 压测,系统在 HTTPs 请求 15QPS 时 VPS 的 CPU 使用率稳定在 20% 左右,搭设自己使用的服务在性能上是完全没问题的

根据我自己的使用情况,一个月流量费最高 9.8 元,平常 5 元/月,假设流量费一年 60 元。为避免恶意访问,VPS 需要设置每天流量消耗上限

我的电脑和路由器正常情况下功率低于 30W,电费按 0.7 元/度算,一年电费小于 200 块

其他费用,比如域名大概每年二十块。这样算起来我一年需要花费 400 元左右

优秀开源工具

Hugo

Hugo,将 Markdown 文件转换为静态网页,结合 Nginx 可以实现静态网站,本网站就是使用 hugo 构建的

Yacy

yacy,开箱即用的自定义搜索引擎,安装配置非常方便,当前网站的 search site 即基于 yacy

Seafile

Seafile,三个主要功能:文件同步与全文搜索 / 个人 Wiki 与全文搜索 / 在线 Word 编辑。三个用户以内,Seafile 的搜索和 Word 编辑功能是免费的

Calibre-Web

Calibre-Web,开源 web 图书管理工具(下面展示的书籍是我自己花钱买的 🤭)

filebrowser

filebrowser,web 远程文件管理与下载工具

Gogs

Gogs,搭建自己的 github 服务。国内访问 github 太慢,可以自己搭建 gogs + VPN 实现部分仓库镜像。当然也可以使用 Gitee

Monitorix / Elastic Stack

Monitorix / Elastic Stack

Monitorix 是轻量级 Linux 系统监控软件,指令行即可安装;Elastic Stack 则是重量级监控工具,功能更丰富,细节请参考官方示例

VPS 网络流量限制

我在 VPS 中使用 vnstat 2.6wondershaper 命令和 Python2 脚本加上 crontab 实现了流量限制,Python2 脚本如下所示:

import datetime
import json
import commands

# vnstat 2.6 and wondershaper must installed
# */1 * * * * python /home/xxx/tmp/net_monitor.py
valid_itf_id = "eth0"
daily_max_traffic = 3.0 # GB

cmd_traffic = 'vnstat --json d 1'
vnstat_res = commands.getoutput(cmd_traffic)

net_info_jsn = json.loads(vnstat_res)
valid_itf = None
for interface in net_info_jsn["interfaces"]:
    if interface["name"] == valid_itf_id:
        valid_itf = interface

log = open("/tmp/net_monitor.log", "a")
time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

if valid_itf != None:
    day_traffic_tx_gb = valid_itf["traffic"]["day"][0]["tx"]/(1024.0*1024*1024.0)
    tmp = ""
    if day_traffic_tx_gb > daily_max_traffic:
        limit_cmd = "/sbin/wondershaper " + valid_itf_id + " 480 480" # tx/rx 60KB/s
        tmp = commands.getoutput(limit_cmd)
        if len(tmp) == 0:
            tmp = limit_cmd
    else :
        clear_cmd = "/sbin/wondershaper clear " + valid_itf_id
        tmp = commands.getoutput(clear_cmd)
        
    res = str(day_traffic_tx_gb) + "|" + tmp + "\n"
    log.write(time_str + "|" + res)
else :
    log.write(time_str + "|no such interface: " + valid_itf_id + "\n")
                                     
log.close()

安装示例

Seafile

seafile 专业版 可免费用于不多于三个用户的场景。访问专业版页面需要将页面语言改为英文。使用 docker-compose.yml 是最简单的安装方法

组件

  1. MySQL

可以从国内镜像或者官网下载,最好安装 5.7 版本,安装可参考这里。此外还需要判断 win 防火墙是否放行

mysql 的安全设置比较麻烦,默认配置可能不支持 root 登录,需要修改并允许 root 登录,细节可参考其他资料 。默认密码修改可以参考这里

  1. OnlyOffice

OnlyOffice 社区版 可用于免费预览与编辑 Office 文档。seafile 安装与开启 onlyoffice 支持请参考这里

# 拉取 onlyOffice 镜像并运行
docker run -i -t -d -p 8702:80 --restart=always onlyoffice/documentserver

seafile 设置 onlyoffice api 地址时需要确定地址是可以访问的,即下面的配置:

ONLYOFFICE_APIJS_URL = 'http{s}://{OnlyOffice domain or IP}/web-apps/apps/api/documents/api.js'
  1. 其他

pro 版 seafile 自身包含了 5.6 版本的 ES 所以不需要额外安装

  1. 安装 seafile

先按照官网的要求安装依赖,然后执行 setup-seafile-mysql.sh。pro 版本不支持 sqlite

常用命令如下:

seahub.sh start-fastcgi  # 查看详细错误

配置

  1. 如果希望网页端预览 office,请参考这里进行设置
  2. 开启 ES 搜索请参考这里
  3. 默认 seafile 的 8000 端口不对外开放,参考这里可以设置非 localhost 访问
  4. 开机启动请参考官网文档

开启 HTTPS

使用 FRP 将内网中的 Seafile 服务端口引导到 VPS 中,随后就可以在 VPS 中通过配置 Nginx 实现 HTTPS 的外网访问。Seafile 配置 HTTPS 访问的方式可以参考官网

修改 proxy_set_header Host $host:CUSTOMPORT ,避免 CSRF 错误

FRP 内网配置示例
[seafile_8000]
type        = tcp
local_ip    = 192.168.8.114
local_port  = 8000
remote_port = 8000
use_encryption = true

[filebrowser_8080]
type        = tcp
local_ip    = 127.0.0.1
local_port  = 8080
remote_port = 8080
use_encryption = true
Nginx 配置示例

利用 Nginx 端口复用功能,只要修改 server_name 就可以在 80/443 端口同时向外提供不同的服务

###################################### Web
server {
    listen 443;
    server_name yearn.xyz;
    ssl on;

    ssl_certificate /etc/xxx/live/xxx/fullchain.pem;
    ssl_certificate_key /etc/xxx/live/xxx/privkey.pem;

    access_log /var/log/nginx/xxx.log;
    error_log /var/log/nginx/xxx.log;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    root /root/web_data/static_web;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

server {
    listen 80;
    server_name yearn.xyz;
    rewrite ^ https://$server_name$request_uri? permanent;

    root /root/web_data/static_web;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

######################################### seafile

server {
    listen 443;
    server_name seafile.yearn.xyz;
    ssl on;

    ssl_certificate /etc/xxx/live/xxx/fullchain.pem;
    ssl_certificate_key /etc/xxx/live/xxx/privkey.pem;

    access_log /var/log/nginx/xxx.log;
    error_log /var/log/nginx/xxx.log;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://127.0.0.1:xxxx;
        proxy_set_header Host $host:443;
        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:xxxx;
        client_max_body_size 0;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout 36000s;
        proxy_read_timeout 36000s;
        proxy_send_timeout 36000s;
        send_timeout 36000s;
    }
}

server {
    listen 80;
    server_name seafile.yearn.xyz;
    rewrite ^ https://$server_name$request_uri? permanent;

    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}
posted @ 2022-01-28 10:48  jiahu  阅读(284)  评论(0编辑  收藏  举报