0x0

一个没有感情的机器人

刚才的一个小时中对网站的基础模板做了一些调整,如果大家在使用中遇到打不开的页面请告知我,谢谢! 本次调整内容:

  • 给网站增加了一个 logo
  • 增加了个人主页的存在感,现在博客名放在页头而不是页脚了。可以通过自定义样式改造这个页头链接,比如给自己制作头像
  • 降低了匿名分享页面(即草稿文章)上网站的存在感,现在应该只有一个 logo

(Yes, 0x0.)

总之介绍一个免费 host 文件/图片/生成短链接的网站 THE NULL POINTER

  • 有效期最多一年(根据文件大小浮动)
  • 通过命令行上传
  • 最大文件尺寸 512 m
  • 拒绝安装包/可执行文件/镜像
  • 拒绝违反德国法律的内容
  • 等等

站点开源,有兴趣可自己搭建。

commento.io 提供了开源 self-hosted 评论服务。

我可以在服务器上安装这个服务,然后给网站的每个页面都配置上评论。

优点是:

  • 有评论了
  • 免费开源
  • 自己拥有数据
  • 如果有别的朋友需要,可以共享评论服务(独立,但是数据在我这)
  • 可以第三方登录,也可以注册账号

缺点是:

  • 网站和评论账号分离
  • 作者不能管理自己的评论区,得由我管理

其他要考虑的问题:我们真的需要评论吗?

如果你有自己的思考或观点请(用随便什么方式)联系我。

(最好的办法还是 implement native comment,可是我真的要去学 go 吗……)

在博客设置的「自定义 #css 」一栏中贴入以下代码:

header.multiuser {
    display: none;
}

然后保存即可。

(如果你的博客是 unlisted 模式,且/或不希望访客注意到本站首页的存在,可以使用以上代码。)

#howto

最近魔改出两个 writefreely 博客主题,贴在设置页的「自定义 #css 」一栏就可以使用。

样式已经基本确定了,第一个是等宽字体、性冷淡风格,起名为「portal」;第二个参考了我一直很喜欢的「kagami」jekyll 主题,私以为是 typography 做得最好的中文静态博客主题。

接下来要做的是微调 markdown 内文格式,完成后就会发布供大家使用。先放预览图:

阅读更多

假如你打开一个长毛象站点,并搜索本站的某个 federation 账号(如 @0x0@matterofti.me 也就是我自己),会发现该用户的确存在,个人信息栏也能显示其发表过的文章数量,但个人时间线很有可能是一片空白——看不到该用户的往期文章推送。

起初,我发现这个现象时,困惑了相当长一段时间,还以为是 writefreely 的 bug。但当我关注了自己的博客,新发布的文章又能显示在时间线里了。

前不久,更新 v 0.12.0 后,为了测试新加入的 mention 也就是 @ 功能,我用不同博客分别 @ 了我自己的长毛象账号。那几篇编辑过的文章也奇迹般地出现在了博客的时间线上。

这些奇特的表现其实是 ActivityPub 协议的实现方式所导致的。

ActivityPub 既然是一个「去中心化」协议,顾名思义,它的宇宙分布在不同的私人服务器上。用户要跨服发布/接收内容,就要进行服务器间的通信。

那么,服务器要如何决定推送给哪些服务器/收取哪些服务器的信息呢?最简单的实现是「我全都要」,把宇宙中每一条信息都拷贝到本地,并对全宇宙广播自己的时间线。但很显然,随着宇宙的扩张,服务器之间的联系(完全图的边数)将会爆炸式增长,这会消耗过多的资源,而且也有违「去中心化」的本意——如果接收和储存所有信息,不就相当于每台服务器都在本地做了个宇宙的镜像吗?

所以,每个服务器只应该接收和自己的用户有关的信息,也就是自己用户「订阅」的信息。广播出去的消息,也只应该送到相关的服务器上。

ActivityPub 的具体实现方式是给每个用户(actor)分配了一个 inbox 和一个 sharedInbox,后者通常是本服务器的公共时间线。当用户发布一条内容 (本站的文章,长毛象的嘟文)时,服务器有几种选择:

  1. 私信——分别发送到每个接收者的 inbox
  2. 分组可见——在内容的 tocc 字段里填写上接收者的 handle,并发送到 sharedInbox
  3. 公共——发送到 sharedInbox

不难发现,在 ActivityPub 的世界里私信和普通内容是平等的,因为它们都只是「发给特定收信人的信息」而已。

这么做的结果就是,假如某个服务器没有人订阅本站的博客,他们还是能通过本站的 ActivityPub 端点拿到基本用户信息(如发布的文章数量),但是文章没有被发送到他们的 sharedInbox,所以时间线才会一片空白。

而由于推送是在「创建」或「编辑」时发生的(!!!),用户也无法看到关注之前的内容,因为它们在发布时没有被送到这个服务器。除非两个 ActivityPub 实例都实现了 outbox 相关功能,这样可以从发布内容者的 outbox 里主动拉取内容。

参考资料

#dev

今天终于把 writefreely 升级到了 0.12.0 版本,有以下几个主要变化:

  • 可以在本站 @ 任何一个使用 ActivityPub 协议的站点(如长毛象)的账号。当然,也可以 @ 本站用户,只是他们不会收到提醒,例如:@0x0@matterofti.me。目前看来,这个功能比较鸡肋,假如你平时用长毛象,那可以考虑用 @ 来推广自己的博客,或者管理订阅列表(手动 @ 自己的读者来看新文章……)。
  • 据说可以用 slack 和 gitlab 进行第三方登录,但我还没摸索出要怎么打开。
  • 导入 .md.txt 文章。

此外还修复了大大小小的 bug。增加了一些页面,配套的翻译还在进行中。

很遗憾,中文标签依然没有实装,我打算再去 github 催一催,或者找机会迁移到 mysql 算了……


简单记录一下这次升级的过程,以资参考。

首先,从服务器备份数据库:

ssh <user>@<your-server>
// windows
pscp.exe <you>@<your-server>:</path/to/your/>writefreely/writefreely.db <local destination>
// -nix
scp <you>@<your-server>:</path/to/your/>writefreely/writefreely.db .

然后下载新的 release 到服务器,解压:

dpkg --print-architecture // 获取本机 cpu 架构
wget https://github.com/writeas/writefreely/releases/download/v0.12.0/writefreely_0.12.0_linux_amd64.tar.gz
tar -zxvf writefreely_0.12.0_linux_amd64.tar.gz

根据官方说明,接下来执行以下几步:

  • 停止服务 systemctl stop writefreely
  • 把 release 目录里所有文件(除了 key/ 目录之外)都复制到工作目录,覆盖原来的文件
  • 重启服务 systemctl start writefreely
  • 更新数据库 scheme writefreely db migrate

但由于我做了本地化,魔改了不少 css 和页面模板,static/, pages/, templates/ 这三个目录不能直接覆盖,需要和 remote git repo 里的版本 merge。之前迟迟没有动手,也是在纠结这一步要怎么做。权衡了各种方案后,最后我决定把 repo clone 到本地,然后在本地手动合并。

我用的工具是 WinMerge,可以对比最多三个文件夹。大部分改动都挺 trivial,只是比较繁琐(有些页面我就顺便翻译了)。注意这个工具会产生一堆 .bak 文件,需手动删除。全部做完后,push 回 repo,再登进服务器 pull 就行了。

这一步不会和其他步骤冲突,可以有闲的时候慢慢处理,等全部文件准备好了再做升级。除了合并静态文件之外,实际升级耗时五分钟左右。

#dev #meta

逛 product hunt 看到出了一个新的博客平台,ʕ•ᴥ•ʔ Bear Blog。点进去发现首页如同本站一样简洁,没有 js/css,同样使用 markdown 写作,可以自定义域名,目前还是全免费的。

计划在做的功能有:

  • 标签/分类
  • LaTeX
  • 代码高亮
  • 个人数据统计
  • 基本自定义 css(等等,说好的无 css 呢)
  • 邮件订阅列表

比本站健全的地方在于有一个 toast(类似于点赞)按钮,任何访客都可以 toast,最小化的社交设计可以让写作不那么寂寞。

这个平台也有一个公共时间线,发表文章时可以选择是否公开。和本站不同的是,公开与否是 per post 而不是 per blog,更加灵活。当然,相对的缺点是每人只有一个博客。

目前还没看到任何备份功能,不过可以去 Issues 提建议。

总之,有兴趣的朋友可以去试试看。

#hunt

#dev

trilium 是一个个人知识库笔记软件,支持同步到自己的服务器上。

参考资料:

首先在 ubuntu 上安装 nodejs 10.x,版本必须在 10.5 之后。然后根据官方指南安装所有依赖:

sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essential nasm libx11-dev libxkbfile-dev

然后克隆最新稳定版源码并安装 npm 包:

git clone -b stable https://github.com/zadam/trilium.git
cd trilium
npm install

这期间我遇到过一个报错:

g++: fatal error: Killed signal terminated program cc1plus

没有搜索到什么解决方法,某个回答说是内存不够,再次运行 npm install 就好了。

到这一步,原本直接运行就可以,但因为这个服务器上还运行了别的应用,我打算把它部署在子域名下,所以需要配置一下端口和反向代理。

/etc/nginx/sites-available/ 下建立 trilium,并写入如下内容:

server {
    listen    80;
    listen    [::]:80;
    server_name    trilium.example.com; // 自定义域名
    location / {
        proxy_pass http://127.0.0.1:8080/; // 自定义端口
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

注意这里有个坑:proxy_pass 必须用 http 协议,否则会 502。

不知为何,我的 /home/[user]/ 目录下并不存在 .local/share,因此只能自己手动建立一个 data directory:

cd ~
mkdir trilium-data
export TRILIUM_DATA_DIR= ~/trilium-data

然后把 config.ini 复制过来:

cp <dir>/trilium/config-sample.ini ~/trilium-data/config.ini

把这个 config.ini 里的端口改掉,就齐活了。

现在可以运行:

cd trilium
nohup node src/www &

这样即使用户登出,还是能在后台运行服务。在这一步又踩了两个坑,一个是没装 sqlite3,于是手动 npm install sqlite3;另一个是提示 DB uninitialized,只要配置正确后跳转到 /setup 完成初次使用导航就好了。

登录和同步完成后,又发现一个问题,就是加载实在太慢。可以调整一下 payload 大小限制,在 server{} 里加上:

client_max_body_size 0;

最后,照例 certbot 配置 SSL 证书,就完成了。其实还有很多不完善的地方,研究 nginx 文档后再回来修改吧。