介绍
云筏(Cloudraft)我印象中应该前年还是大前年开始在V2做广告,之前代理百度CDN,现在做大内存共享超算,所以产品根据用途的不同分为计算,内存和其他三类。欧洲机房对比之下,大硬盘,价格也美丽,背靠Hetzner非常适合建站使用。

之前买过云筏的百度云CDN接入服务,这次看到这家VPS有活动就买来玩了一下(
先上配置(图片1)

捕获.PNG
目测是挂PT&网盘小能手的机器,
如果想用来下种子,不是Hostsolution那种抗投诉线路,可靠性性有待考量
~当然如果是月付党下了转OD之类的然后跑路当我没说~

中国电信、联通、移动和全球到服务器上的上传及下载速度。
可以看到,在bbr的加持下,尽管机器远在欧洲,但是联通CU还是有一个比较不错的表现。
同时在全球的表现上,可以维持到官方的标称300M带宽,也算是比较良心的地方。

实际建站体验:
我选择自带的Ubuntu 18.04 + Podman完成平台搭建
Podman相对Docker在API上面设计更为现代化和简洁易用,更容易和Systemd等系统服务集成,并且可以运行在rootless下,安全性和便捷性更好。

#到手升个级,并安装podman
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key" | sudo apt-key add -
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install podman

podman 回显:(不感兴趣可以跳过,里面有这个环境一些内核细节

root@PSSns6nuDf:~# podman info
host:
  arch: amd64
  buildahVersion: 1.19.4
  cgroupManager: systemd
  cgroupVersion: v1
  conmon:
    package: 'conmon: /usr/libexec/podman/conmon'
    path: /usr/libexec/podman/conmon
    version: 'conmon version 2.0.27, commit: '
  cpus: 1
  distribution:
    distribution: ubuntu
    version: "18.04"
  eventLogger: journald
  hostname: PSSns6nuDf
  idMappings:
    gidmap: null
    uidmap: null
  kernel: 4.15.0-20-generic
  linkmode: dynamic
  memFree: 188493824
  memTotal: 1013776384
  ociRuntime:
    name: crun
    package: 'crun: /usr/bin/crun'
    path: /usr/bin/crun
    version: |-
      crun version 0.18.1-7931a-dirty
      commit: 7931a1eab0590eff4041c1f74e2844b297c31cea
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +YAJL
  os: linux
  remoteSocket:
    path: /run/podman/podman.sock
  security:
    apparmorEnabled: true
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_                                                                                                                                                                                                                                             NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: false
    seccompEnabled: true
    selinuxEnabled: false
  slirp4netns:
    executable: ""
    package: ""
    version: ""
  swapFree: 1980796928
  swapTotal: 1989525504
  uptime: 151h 57m 15.99s (Approximately 6.29 days)
registries:
  search:
  - docker.io
  - quay.io
store:
  configFile: /etc/containers/storage.conf
  containerStore:
    number: 0
    paused: 0
    running: 0
    stopped: 0
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /var/lib/containers/storage
  graphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Using metacopy: "false"
  imageStore:
    number: 0
  runRoot: /run/containers/storage
  volumePath: /var/lib/containers/storage/volumes
version:
  APIVersion: 3.0.0
  Built: 0
  BuiltTime: Thu Jan  1 08:00:00 1970
  GitCommit: ""
  GoVersion: go1.15.2
  OsArch: linux/amd64
  Version: 3.0.1

在Podman里面部署宝塔国际版(aapanel)

为啥不用国内版...已经懒得吐槽绑定手机强制注册还有去年那个安全漏洞了,
然后这玩意有个叫aapanel的国际版
如果有人说国际版没有中文,那建议还是用国内版吧,
然后有人做了这玩意的docker容器,直接伸手
帮助见:https://hub.docker.com/r/pch18/baota

一键安装
创建需要的数据目录

 mkdir ~/mysql_data
 mkdir -p  ~/aapanel/wwwroot
 mkdir  ~/vhost
 mkdir ~/aapanel/logs

拉取镜像

root@PSSns6nuDf:~# podman run -dt  -p 80:80 -p 443:443 -p 888:888 -p 8888:8989 -p 21:21  -v ~/aapanel/wwwroot:/www/wwwroot  -v ~/mysql_data:/www/server/data  -v ~/vhost:/www/server/panel/vhost  -v ~/aapanel/logs:/www/wwwlogs  adam3278/aapanel

默认密码为
aapanel/aapanel123 记得及时修改

起飞:
2捕获.PNG

需求

早期使用习惯:

大概从高中开始我就用群晖的东西来管理我的个人文件,设备先后从 Gen8 黑群晖 —— DS 216j —— 之前的 Gen10 Plus 黑群晖
在这个时间段中,主要用途为:
群晖搭配 Download Station 下载东西
使用 Samba 作为分享给 Windows/电视盒子 的协议

现在的需求:

面向局域网内容器共享硬盘空间
足够快的媒体搜索,可方便的让我在不手动归类的情况下找到我想要的文件
提供面向对象存储的API
稳定,可以接受复杂的首次部署但要简单的升级和日常维护
无明显的直接经济支出或者可以一次付款终身使用

  • High Hardware cost and Low Software cost

- 阅读剩余部分 -

var WechatAPI = require('wechat-api');
var api = new WechatAPI(wechatappid, wechatsecret);

var storedCookies = require('./cookies.json');

var dateId = new Date(new Date().toUTCString())
var tempature = function () {
    min = Math.ceil(35);
    max = Math.floor(37);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}()



const Nightmare = require('nightmare')

const { doesNotThrow } = require('assert');
var currentUrl = '';
var vo = require('vo');

function* run() {
    const nightmare = Nightmare({
        show: true,
        maxHeight: 16384,
        maxWidth: 16384,
        width: 600,
        height: 1200,
    })
    if (!storedCookies.length) {
        storedCookies = {}
    }
    yield nightmare.goto('about:blank');


    var url = yield nightmare

        .goto('http://wdt.wbu.edu.cn:9999/wxfwdt/html/wxfwd')
        .cookies.set(
            storedCookies
        )
        .wait(500)
        .url()
        .then(
            url => {
                return url
            })
    if (url.split('/')[2] != "wdt.wbu.edu.cn:9999") {
        console.log(url.split('/'))
        yield nightmare
            .type('#username', userme)
            .type('#password', pass)
            .check('#rememberMe')
            .click('#login_submit')
            .cookies.get()
            .then((cookies) => {
                console.log(cookies)
                require('fs').writeFileSync(
                    'cookies.json',
                    JSON.stringify(cookies, null, 4)
                );
            })
    }
    var dimensions = yield nightmare
        .wait(5000)
        .evaluate(() => {
            var allButtons = document.getElementsByClassName('service-text');
            for (var i = 0; i < allButtons.length; i++) {
                if (allButtons[i].innerText == '健康上报') allButtons[i].id = 'loginbutton';
            }
        })
        .click('div[id=loginbutton]')
        .type('input[name=tw]', tempature)
        .click('#weuiAgree')
        .click('#qrtj')
        .evaluate(function () {
            var body = document.querySelector('body');
            return {
                width: body.scrollWidth,
                height: body.scrollHeight
            }
        })

    var dimensions = yield nightmare.evaluate(function () {
        var body = document.querySelector('html');
        return {
            width: body.scrollWidth,
            height: body.scrollHeight
        }
    })
    console.log(dimensions.width)
    nightmare.viewport(dimensions.width, dimensions.height)
        .wait(1000)
        .screenshot(dateId + '.png');

}

vo(run)(function () {
    console.log('done');
    let data = {
        "temp": {
            "value": tempature,
            "color": "#173177"
        }
    }
    api.sendTemplate(openId, templateId, prefixHost+dateId+'.png',
        data, function (err, data) {
            if (err) {
                console.log(err);
            }
        }
    );
});

操作后果自负,我不会提供任何保证。

结合上面一篇文章到《Quest2 一种无需路由器插件的激活方法》完成网络认证并卡在0%升级的时候进行,结合前文可以实现无软路由,无需电脑全局。只需要手机fq激活开发者和一台电脑,即可完成全部激活操作。

离线升级包云盘链接:https://cloud.189.cn/t/2iy6nymee6jy(访问码:9glx)
下载后重命名为UPDATE.zip
步骤

确认Sidequest已经成功连接到你的头显
接下来打开 C:\Users\你的用户名\AppData\Roaming\SideQuest\platform-tools 中的 platform-tools 文件夹,并双击资源管理器地址栏,输入 cmd 并回车(找不到可以搜索platform-tools)
按顺序执行以下命令,并回车
adb reboot bootloader
等待至少10秒
fastboot oem reboot-sideload
等待至少10秒
adb sideload UPDATE.zip

操作前注意

  • 由于使用到了Github SSH 协议 Clone,请先在 Github 后台添加你本机的 SSH 公钥
  • 并在本机执行 ssh git@github.com

Snipaste_2020-12-30_18-11-54.png
看到这样的回显说明绑定成功,可以使用 SSH 协议进行操作。
2020-12-30 17-45-7.png
前往 idc.wiki 购买并开通SCP账户 这里我使用一元试用
付款后进入后台
这个时候需要获取一下github的拉取ip
简单的nslookup一下即可,我使用的是这样的配置
由于HTTPS协议存在证书校验,所以转发HTTPS是行不通的,我们转发SSH(即TCP)
在后台创建一条转发
2020-12-30 17-48-51.png

状态为创建完成后,就可以看到生成的转发操作
我们进行一次pull操作,以下是速度对比

直连线路 联通商宽
Snipaste_2020-12-30_18-20-05.png

中专线路 上海CN2
Snipaste_2020-12-30_18-14-22.png

提升不明显,电信常年100K拉取
Q:但是使用流量转发服务创建的都是高位端口,不易输入,这个时候该怎么办
A:需要自行对本机端口转发进行处理,Linux上面写死Github的Hosts然后iptables转发一下到ip的22变成你获取的转发ip即可,至于Windows 我也不会

需要材料:

  • 已经登录Oculus客户端的手机,且已经注册好开发者用户
  • SideQuest

首先手机正常绑定设备,带上头显输入五位PIN,确保手机APP里面给头显开启开发者模式
(手机需要挂梯子,手机和头显连到同一个wifi,头显不用挂梯子)
接下来打开SideQuest,
1.png
点击Custom Command
在自定义命令中输入下面两行
adb shell settings put global captive_portal_https_url https://connect.rom.miui.com/generate_204
2.png
点击下面的RUN
接下来再执行执行
adb shell settings put global captive_portal_http_url http://connect.rom.miui.com/generate_204

连接WIFI 显示状态为已连接 , 进入下一步。
如果卡在更新 0% 请等待,
个屁咧,不会真的有人以为一直等就可以把,不会吧不会吧不会吧。

接下来需要一点点技术操作。
一般正常的思路是直接安装梯子APk,但是这次不行,在完成首次更新之前你安装任何APK都会显示加载。
通过日志我发现是缺少了发送给Launcher的intent callback导致应用无法显示。
那么...我们再安装一个Launcher...是不是就行了(?
答案是,可以,而且这种Launcher Quest应用商店里面就有一个
https://sidequestvr.com/app/199/quest-app-launcher
就是上面这货,我们现在更新界面,插上USB线,给它安装一下
然后怎么启动这货呢?
点击sidequest上面的九宫格,看到刚刚安装的launcher,点旁边的齿轮,选择Launch APP
接下来配置好你用的梯子,如果自动重启,不用担心,打开你的手机,再次激活开发者模式,完成后面的步骤。
启动好梯子以后,静静的等待后台自动更新,由于你用了第三方启动器,所以你也看不到进度,一般等激活流量达到150M+,就可以手动重启头显。

Snipaste_2020-12-28_00-28-58.png
完成更新后,即可正常使用**
教程结束

基本操作为(上下划动小翻页,左右划动大翻页,左右边栏触碰即翻页,同时屏蔽普通的页内划动)

原始脚本(不建议直接导入Via或者其他支持用户脚本的浏览器页面,可以导入的版本在下面):

//适配300 DPI下的墨案Inkpad X Via浏览器翻页脚本
//此DPI下浏览器分辨率为906x1208
//如果DPI不一致请修改下面的变量
// version:0.1.0
// Date:2020-7-10
window.addEventListener('load', function(){
  //配置区
  var smallScrollGap = 300, //小翻页的间隔(上划下划)
    bigScrollGap = 1150,  //大翻页的间隔(左划右划)
    edgeAreaSize = 0.05, //侧边检测区域的大小
    threshold = 80, //最小的动作触发检测间隔
    restraint = 100, // 最大的跨坐标轴位移(比如当前是横向手势,其在滑动中产生的纵向位移)
    allowedTime = 400, // 一次操作最大的触发时间(ms)
    upDownState = -1, //1或-1,该选项影响是手指方向滚屏还是逆手指方向滚屏(纵向)
    leftRightState = 1, //1或-1,该选项影响是翻书方向滚屏还是逆翻书方向滚屏(横向,该选项也会影响左右两侧的触碰区域)
    debugMode = 0; //调试模式开关,影响调试输出
    //配置结束,进入逻辑
    //处理滑动逻辑
    var el = document.querySelector("html");
    if(el){
    swipedetect(el, function (swipedir) {
      if(debugMode ==1){
      console.log("scrool to " + swipedir);
    }
      //   swipedir = {"none", "left", "right", "up", "down"}
      if (swipedir == "left") {
          window.scrollBy(0, leftRightState * bigScrollGap);
      } else if (swipedir == "right") {
          window.scrollBy(0, -leftRightState * bigScrollGap);
      } else if (swipedir == "up") {
        window.scrollBy(0, upDownState * smallScrollGap);
      } else if (swipedir == "down") {
        window.scrollBy(0, -upDownState * smallScrollGap);
      }
    });
  }
  //获取页宽和页高
  function getWidth() {
    return Math.max(
      // document.body.scrollWidth,
      // document.documentElement.scrollWidth,
      // document.body.offsetWidth,
      // document.documentElement.offsetWidth,
      // document.documentElement.clientWidth
      screen.availWidth
    );
  }
  
  function getHeight() {  //页高,下一个版本做边栏上下区域不同功能用得到
    return Math.max(
      document.body.scrollHeight,
      document.documentElement.scrollHeight,
      document.body.offsetHeight,
      document.documentElement.offsetHeight,
      document.documentElement.clientHeight
    );
  }
    //滑动方向检测
    function swipedetect(el, callback) {
        var touchsurface = document.querySelector("html"),//找寻HTML节点注入事件
        swipedir,
        startX,
        startY,
        distX,
        distY,
        elapsedTime,
        startTime,
        handleswipe = callback || function (swipedir) {};

      touchsurface.addEventListener(
        "touchstart",
        function (e) {
          var touchobj = e.changedTouches[0];
          swipedir = "none";
          var dist = 0;
          startX = touchobj.pageX;
          startY = touchobj.pageY;
          //这里采用屏幕坐标进行边界特判
            console.log("screen Pos x,y:"+touchobj.screenX+','+touchobj.screenY);   
            // 左右侧单击特判
            var PageX_MAX = touchobj.screenX;
            if(getWidth() - PageX_MAX < edgeAreaSize * getWidth())
               {
                     swipedir = "down";
               }
               else if(PageX_MAX < edgeAreaSize * getWidth())
               {
                     swipedir = "up";
               }
          startTime = new Date().getTime(); // 记录动作开始时间
          //e.preventDefault();
        },
        { passive: false }
      );

      touchsurface.addEventListener(
        "touchmove",
        function (e) {
          e.preventDefault(); // 阻止元素滑动
        },
        { passive: false }
      );

      touchsurface.addEventListener(
        "touchend",
        function (e) {
          var touchobj = e.changedTouches[0];
          distX = touchobj.pageX - startX; //获取横纵坐标的位移向量
          distY = touchobj.pageY - startY;
          elapsedTime = new Date().getTime() - startTime; // 获得总动作时长
          if (elapsedTime <= allowedTime) {
            //判断动作是否超时
            if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint) {
              //计算位移
              swipedir = distX < 0 ? "left" : "right"; // 如果 distX 是个负值,那么是移动是自右向左(坐标轴正半轴到负半轴),反之亦然
            } else if (
              Math.abs(distY) >= threshold &&
              Math.abs(distX) <= restraint
            ) {
              // 纵向检测
              swipedir = distY < 0 ? "up" : "down"; // 如果 distY 是个负值,那么是移动是自上向下(坐标轴正半轴到负半轴),已经说过了
            }
          }
          handleswipe(swipedir);
          //e.preventDefault();
        },
        { passive: false }
      );
    }
  }, false) //脚本结束

压缩后的脚本(可以导入支持脚本的浏览器,在线安装页面施工中):

window.addEventListener("load",function(){var e,o,a,c,t,s,r,n,d;function i(){return Math.max(screen.availWidth)}debugMode=0,document.querySelector("html")&&(e=function(e){1==debugMode&&console.log("scrool to "+e),"left"==e?window.scrollBy(0,1150):"right"==e?window.scrollBy(0,-1150):"up"==e?window.scrollBy(0,-300):"down"==e&&window.scrollBy(0,300)},n=document.querySelector("html"),d=e||function(e){},n.addEventListener("touchstart",function(e){var n=e.changedTouches[0];o="none";a=n.pageX,c=n.pageY,console.log("screen Pos x,y:"+n.screenX+","+n.screenY);var t=n.screenX;i()-t<.05*i()?o="down":t<.05*i()&&(o="up"),r=(new Date).getTime()},{passive:!1}),n.addEventListener("touchmove",function(e){e.preventDefault()},{passive:!1}),n.addEventListener("touchend",function(e){var n=e.changedTouches[0];t=n.pageX-a,s=n.pageY-c,(new Date).getTime()-r<=400&&(80<=Math.abs(t)&&Math.abs(s)<=100?o=t<0?"left":"right":80<=Math.abs(s)&&Math.abs(t)<=100&&(o=s<0?"up":"down")),d(o)},{passive:!1}))},!1);

如果对我提供的脚本效果不满意,可以自行修改配置区块然后生成新的压缩脚本

将修改后的代码粘贴在 https://jscompress.com/ 中,随后单击下方'Compass JavaScript',将压缩后的脚本导入即可。

可能会写一个系列

粗暴的方法
mount --bind /usr/bin/true /usr/bin/mandb
unmount #After installition
好一点的方法
echo "Preseeding man-db/auto-update to false"
echo "man-db man-db/auto-update boolean false" | debconf-set-selections
echo
echo "Configuring dpkg to not fsync()"
echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/02speedup
apt-get update
EOF