Misskey 是一个支持 ActivityPub 协议的去中心化社交平台。本文将介绍如何手动搭建属于自己的 Misskey 实例,并以 AWS S3 为例为其配置对象存储以及对象存储所用的反向代理,还将介绍如何为 Misskey 实例安装并启用全文搜索引擎 Elasticsearch。
大约在两年前,Twitter 修改了它的服务条款并封禁了一大批 “未成年” 用户。在这些被封禁的 Twitter 用户中,有些便逃往了一个叫做 Mastodon 的平台,这便是我第一次接触到 Mastodon 这个平台,同时也了解到了联邦宇宙这个概念。
联邦宇宙(Fediverse)是一系列软件平台的集合。从它的名字中也可以很直观地了解其含义:如果将一台运行着那些特定软件平台的服务器或者实例比作一个星球,那么联邦宇宙便是一个有着不计其数的星球与居民的广袤世界。每个居民都可以自由地选择他们自己想要居住的星球,星球与星球之间则可以通过如 ActivityPub 一类的通信协议互相连接。与大家常用的 Twitter 等社交平台相反,在联邦宇宙的世界里并没有中心服务器的概念,这里的每个星球互相之间都是平等的。你可以自由加入你喜欢的服务器,也可以创建属于你自己的服务器。
联邦宇宙中的平台其实也有不同的种类。如上图所示,有类似于 Twitter 的社交平台,也有类似于 Instagram 的媒体分享平台,当然还有一些文件分享平台等等。不同类型的平台之间都可以通过统一的通信协议互联,而 Mastodon 则是联邦宇宙中最有代表性的社交平台,中文俗称 “长毛象”。当然除了 Mastodon 以外,还有如 Misskey 与 Pleroma 之类的社交平台,每一个社交平台都有自己的风格与特性。我曾经用过一段时间 Mastodon,所使用的实例是中文圈最著名的长毛象实例 “草莓县”。这里有着联邦宇宙中最早的一批用户,有因为豆瓣日益严峻的审查制度而加入长毛象的豆瓣难民,有上文中所提到的推特难民,也有纯粹对主流社交平台与环境不满,或者希望保护自己隐私之类的用户。
Mastodon 给我的第一感觉就是 UI 不太好看,给人一种很死板的感觉,而 Misskey 则正好相反。至少对我而言,Misskey 的 UI 是真的直戳我的审美,并且由于 Misskey 诞生于日本,其所拥有的部分二次元元素也很吸引我。下图便是 Misskey 官方为其设计的看板娘形象。
Misskey 是在 2014 年诞生于日本的。早期的 Misskey 并不是一个去中心化的社交平台,甚至连社交平台都不是。后来经过慢慢的更新迭代,并在 2018 年引入对 ActivityPub 协议的支持而成为大家现在所看到的模样。Misskey 最早使用 PHP + MySQL + jQuery 的组合,而现在则使用 Node.js + PostgreSQL + Vue.js 进行开发。在 Misskey 的官网上给出了很详细的 Misskey 实例搭建教程,官方首推的搭建方案为 Docker,除此以外还有一键部署脚本可以使用。由于博主存在一定程度上原因未知的赛博洁癖,本文将以纯手动的方式搭建 Misskey 所需的运行环境及程序本体,同时还会介绍对接对象存储 AWS S3 以及启用全文搜索引擎 Elasticsearch 的方法。
本文所使用的服务器操作系统为 Debian 11,主要运行环境与组件为 Node.js、PostgreSQL、Redis、Nginx,所用 Node.js 包管理器为 Yarn,用于演示的域名为 m.eri.cx。本文中的操作步骤同时适用于 x86-64 平台以及 ARM 平台。为了节约时间,所有软件包均使用 APT 包管理器进行安装。
首先更新软件列表并安装必要软件包:
apt update
apt install wget curl vim gpg
获取并导入所需要的软件源密钥并添加软件源:
curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor > /usr/share/keyrings/nginx-archive-keyring.gpg
curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor > /usr/share/keyrings/nodejs-archive-keyring.gpg
curl -s https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor > /usr/share/keyrings/yarn-archive-keyring.gpg
curl -s https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql-archive-keyring.gpg
curl -s https://packages.redis.io/gpg | gpg --dearmor > /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/debian bullseye nginx" > /etc/apt/sources.list.d/nginx.list
echo "deb [signed-by=/usr/share/keyrings/nodejs-archive-keyring.gpg] https://deb.nodesource.com/node_18.x bullseye main" > /etc/apt/sources.list.d/nodejs.list
echo "deb [signed-by=/usr/share/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian stable main" > /etc/apt/sources.list.d/yarn.list
echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" > /etc/apt/sources.list.d/postgresql.list
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb bullseye main" > /etc/apt/sources.list.d/redis.list
重新更新软件列表并安装所需软件包:
apt update
apt install nginx nodejs yarn postgresql redis git build-essential python3 certbot ffmpeg moreutils
使用 APT 包管理器安装的 Redis 默认没有配置开机自启,需要手动设置开机自启:
systemctl enable redis-server
随后需要为 Misskey 建立运行所需的数据库以及对应的数据库用户。但在此之前,推荐使用 PGTune 对 PostgreSQL 的配置文件进行一些调整以最大化数据库性能:
vim /etc/postgresql/14/main/postgresql.conf
由于 PostgreSQL 默认启用了对等认证,所以我们需要切换到 postgres 用户才能进入到 PostgreSQL 的命令行界面:
su - postgres
psql
此时应该成功进入 PostgreSQL 的命令行界面。下一步开始创建 Misskey 运行所需的数据库及其对应用户,请注意将所有尖括号标注的部分替换为你自己的设置:
create database <数据库名称>;
create user <数据库对应用户的用户名> with encrypted password '<数据库对应用户的密码>';
grant all privileges on database <数据库名称> to <数据库对应用户的用户名>;
\q
接下来开始编译安装 Misskey 本体。首先需要单独为 Misskey 创建一个用户:
adduser --disabled-login misskey
切换到 misskey 用户并拉取 Misskey 本体及其子程序:
su - misskey
git clone -b master https://github.com/misskey-dev/misskey.git
cd misskey
git submodule update --init --recursive
复制并修改默认配置文件:
cp .config/example.yml .config/default.yml
vim .config/default.yml
请修改该配置文件中的网址及数据库配置部分,另外请取消注释 “signToActivityPubGet: true” 这一行,配置文件中的其他部分可以不用修改。
配置文件修改完成后,开始安装 Misskey 所需的组件并编译程序本体:
yarn install
NODE_ENV=production yarn build
初始化 Misskey:
yarn run init
如果在这一步有报错的话,请结合报错信息检查配置文件中的参数是否填写正确。如果一切正常的话,便可输入 exit 退出 misskey 用户。
为 Misskey 配置 Systemd 服务:
vim /etc/systemd/system/misskey.service
Systemd 配置文件示例如下。其中,Misskey 运行所生成的 log 会添加时间戳后保存到 `/home/misskey/misskey.log` 文件内。该日志文件可能会随着使用而逐渐变得很大,因此可根据个人需求配置 logrotate 服务。其他配置文件内容请根据自己的需求进行修改:
[Unit]
Description=Misskey daemon
[Service]
Type=simple
User=misskey
ExecStart=/usr/bin/bash -c "/usr/bin/yarn start 2>&1 | ts >> /home/misskey/misskey.log"
WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production"
TimeoutSec=60
Restart=always
[Install]
WantedBy=multi-user.target
启动 Misskey:
systemctl enable --now misskey
此时便可以通过 `http://IP:3000` 来访问 Misskey 了。但基本上不会有人直接这么用的吧,所以接下来还需要使用 Nginx 为 Misskey 配置反向代理。
建立 Misskey 所用的 Nginx 反向代理配置文件:
vim /etc/nginx/conf.d/m.eri.cx.conf
以下给出 Nginx 配置文件的示例。当前先使用 ssl-cert 所生成的自签名证书,等到后续申请完 Let’s Encrypt 证书后再修改 SSL 证书。记得修改配置文件中所有出现的 `m.eri.cx` 为你自己的域名,其他部分请按照自己的实际情况进行修改:
proxy_cache_path /var/cache/nginx/misskey_cache levels=1:2 keys_zone=misskey_cache:16m max_size=1g inactive=1d use_temp_path=off;
server {
listen 80;
listen [::]:80;
server_name m.eri.cx;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ { allow all; }
location /.well-known/pki-validation/ { allow all; }
location / { return 301 https://$server_name$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name m.eri.cx;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
#ssl_certificate /etc/letsencrypt/live/m.eri.cx/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/m.eri.cx/privkey.pem;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 1G;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_hide_header Strict-Transport-Security;
proxy_buffering on;
proxy_cache misskey_cache;
proxy_cache_lock on;
proxy_cache_use_stale updating;
proxy_cache_background_update on;
add_header Strict-Transport-Security max-age=15768000;
add_header X-Cache-Status $upstream_cache_status;
}
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
启用 Nginx 并申请 Let’s Encrypt 证书,记得将尖括号标注的部分替换为你自己的域名与邮箱:
systemctl start nginx
certbot certonly --agree-tos -m <你的联络邮箱> --no-eff-email --webroot -w /usr/share/nginx/html -d <你的域名>
成功获取证书后,便可以重新编辑 Nginx 配置文件,并将 `ssl_certificate` 与 `ssl_certificate_key` 后面的路径更改为你所申请证书的路径。certbot 默认证书存放路径为 `/etc/letsencrypt/live/<你的域名>`。保存配置文件后,输入 `systemctl restart nginx` 重启 Nginx,此时便可以通过你自己的域名访问 Misskey 了。
Misskey 默认会将用户所上传的图片等文件存放在程序运行目录下的 `files` 目录内,请记得备份这个目录。不过你也可以启用对象存储来让 Misskey 直接将文件上传至对象存储服务器中。请在 Misskey 的后台管理页面内根据网页提示配置对象存储服务。任何兼容 S3 协议的对象存储,不管是 AWS 还是 Wasabi 甚至自建的 MinIO 都可以在 Misskey 中使用。不过大家都知道有些对象存储的流量费还是比较贵的,特别是对于 AWS 这种大厂来说。如果对象存储里的文件被别人拿来刷流量的话,那么下个月的信用卡账单会变得非常好看。所以最好为对象存储设置反向代理来节约流量并隐藏对象存储的相关信息。
接下来将以 AWS S3 为例,介绍如何配置存储桶策略来保护你的对象存储,同时使用反向代理来节约流量并保护自己的对象存储信息。示范所用存储桶的名称为 `eric2369`,所用 IAM 用户的用户名为 `eric2369`。请注意在创建该 IAM 用户的时候不要为其分配任何访问权限,同时在存储桶的权限设置内也请勾选 “阻止公有访问的存储桶设置”。这样可以保证在默认情况下,除了使用根账户用户通过网页控制台访问外,没有其他任何用户可以访问存储桶内的文件。需要访问的用户可以通过编辑存储桶策略赋予该 IAM 用户所需的访问权限。存储桶策略示例如下:
{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "AllowAllUserToGetObjectFromSpecificIp",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::eric2369/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"141.147.183.95/32"
]
}
}
},
{
"Sid": "AllowSpecificUserToGetPutDeleteObjectFromSpecificIp",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/eric2369"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::eric2369/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"141.147.183.95/32"
]
}
}
}
]
}
其中 `arn:aws:s3:::eric2369` 为你所使用的存储桶的资源名称,`arn:aws:iam::123456789012:user/eric2369` 为你所使用的 IAM 用户的资源名称,`141.147.183.95/32` 为你后续要配置反向代理所用服务器的 IP 或你信任的 IP 段。该存储桶配置只允许用户通过你信任的 IP 获取存储桶内的文件,且只有 `eric2369` 用户才能通过该 IP 上传或者删除存储桶内的文件。
接下来为对象存储配置反向代理。你可以使用一个不同的域名如 `files.m.eri.cx` 来作为对象存储所用的反向代理域名,或者像我接下来所演示的一样,使用不同的路径如 `m.eri.cx/misskey-file` 来作为反向代理域名。后者的好处是可以少添加一条解析,少申请一个证书,总之就是懒。
修改上文中 Misskey 的 Nginx 配置文件,示例如下:
proxy_cache_path /var/cache/nginx/misskey_cache levels=1:2 keys_zone=misskey_cache:16m max_size=1g inactive=1d use_temp_path=off;
proxy_cache_path /var/cache/nginx/misskey_file_cache levels=1:2 keys_zone=misskey_file_cache:16m max_size=100g inactive=1y use_temp_path=off;
server {
listen 80;
listen [::]:80;
server_name m.eri.cx;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ { allow all; }
location /.well-known/pki-validation/ { allow all; }
location / { return 301 https://$server_name$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name m.eri.cx;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_certificate /etc/letsencrypt/live/m.eri.cx/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/m.eri.cx/privkey.pem;
#ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
#ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 1G;
location /misskey-file {
proxy_pass https://eric2369.s3.ap-east-1.amazonaws.com;
proxy_ignore_headers X-Accel-Expires;
proxy_ignore_headers X-Accel-Charset;
proxy_ignore_headers X-Accel-Buffering;
proxy_ignore_headers X-Accel-Limit-Rate;
proxy_ignore_headers X-Accel-Redirect;
proxy_ignore_headers Vary;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header x-amz-bucket-region;
proxy_hide_header x-amz-version-id;
proxy_hide_header Set-Cookie;
proxy_hide_header access-control-allow-methods;
proxy_hide_header access-control-allow-origin;
proxy_hide_header Cache-Control;
proxy_hide_header storage_tier;
proxy_hide_header etag;
proxy_hide_header x-api-id;
proxy_buffering on;
proxy_cache misskey_file_cache;
proxy_cache_lock on;
proxy_cache_use_stale updating;
proxy_cache_background_update on;
proxy_cache_valid 200 304 1y;
proxy_cache_bypass 0;
proxy_no_cache 0;
add_header Strict-Transport-Security max-age=15768000;
add_header Cache-Control max-age=31536000;
add_header CDN-Cache-Control max-age=31536000;
add_header X-Cache-Status $upstream_cache_status;
expires 1y;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_hide_header Strict-Transport-Security;
proxy_buffering on;
proxy_cache misskey_cache;
proxy_cache_lock on;
proxy_cache_use_stale updating;
proxy_cache_background_update on;
add_header Strict-Transport-Security max-age=15768000;
add_header X-Cache-Status $upstream_cache_status;
}
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
可以看到,相比之前的配置文件而言,主要是新增了一个 location 段以及一个缓存域。该配置文件会将 `m.eri.cx/misskey-file` 路径下的请求缓存 1 年,最大缓存大小设定为 100GB。这些参数可以根据自己的服务器实际情况进行修改。配置完并重启 Nginx 后,便可以去 Misskey 的管理后台,将对象存储中的 Base URL 更改为 “https://m.eri.cx”,前缀更改为 “misskey-file”,存储桶名称与可用区按照实际情况填写,勾选 “使用SSL” 并取消勾选 “使用代理”、“上传时设置为public-read”、“s3ForcePathStyle” 这几个选项即可。此时你通过 Misskey 上传到 AWS S3 上的文件会在第一次被请求时缓存到 Nginx 的缓存目录下,缓存有效期为一年。这样便可以减少访问存储桶内的文件所产生的流量费用,并且由于隐藏了请求中所有有关于存储桶的头部信息,其他人无法得到你的存储桶信息,即使得到了存储桶信息也会因为存储桶策略的限制而无法访问。
接下来介绍一下如何为 Misskey 启用 Elasticsearch 全文搜索引擎。对于 Mastodon 来说,由于默认禁用了基于数据库的全文搜索功能,所以只能依赖 Elasticsearch 来实现全文搜索功能。但 Misskey 默认启用了基于数据库的全文搜索功能,其实这对于大部分人来说是够用的。但是使用 Elasticsearch 的话可以获得更准确的搜索结果。对于 Misskey 而言,还可以使用 PGroonga 这样一个基于 PostgreSQL 的全文搜索插件。使用这个插件会比使用 Elasticsearch 更加简单,占用的资源也更少。但是我自己也没有长时间使用过这个插件,也不知道和 Elasticsearch 相比谁的搜索结果更合理。关于 PGroonga 的安装与使用,因为步骤较为简单且网上也有相应的教程,本文便不再赘述,主要介绍一下 Elasticsearch 8 的安装与使用。网络上关于 Elasticsearch 的教程大多使用的是 Elasticsearch 7,但是目前最新的版本为 Elasticsearch 8。有些人对 Elasticsearch 8 的评价是 8 相比 7 的升级幅度太大,导致很多以前的教程都不适用。说实话,不管是 7 还是 8 都已经远远超出了我的使用能力范围。我对着 Elasticsearch 8 的文档愣是什么都看不明白。但本着用新不用旧的精神,还是硬着头皮使用 Elasticsearch 8 好了。
首先获取并导入 Elasticsearch 的软件源密钥并添加软件源:
curl -s https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor > /usr/share/keyrings/elasticsearch-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-archive-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" > /etc/apt/sources.list.d/elasticsearch.list
接下来更新软件列表并安装 Elasticsearch。请注意,由于后面还会为 Elasticsearch 安装中文分词插件 IK Analysis for Elasticsearch 以及简繁转换插件 STConvert Analysis for Elasticsearch,而插件的版本必须与 Elasticsearch 版本相同才行。虽然可以通过修改插件中的配置文件来更改插件所适配的版本号,但还是最好先去 GitHub 上查看这两个插件的最新适配版本,并安装与之对应的 Elasticsearch 版本。本文以 Elasticsearch 8.2.0 作为示范:
apt update
apt install elasticsearch=8.2.0
在安装过程中会自动生成默认管理员用户,用户名为 `elastic`,密码会显示在屏幕上,注意记录下来,后面会用到。
继续安装中文分词插件以及简繁转换插件:
/usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.2.0/elasticsearch-analysis-ik-8.2.0.zip
/usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-stconvert/releases/download/v8.2.0/elasticsearch-analysis-stconvert-8.2.0.zip
由于 Elasticsearch 默认状态下会自动打开 SSL 加密,所以需要修改 Elasticsearch 配置文件将其关闭:
vim /etc/elasticsearch/elasticsearch.yml
将该文件中的 `xpack.security.http.ssl:enabled` 修改为 `xpack.security.http.ssl:false` 并保存退出。
接着便可以启动 Elasticsearch 了:
systemctl enable --now elasticsearch.service
修改 Misskey 配置文件:
vim /home/misskey/misskey/.config/default.yml
将之前记录下的 Elasticsearch 管理员用户的用户名与密码填入配置文件中,其他部分保持不动即可。重启 Misskey 后,试试看网页中的搜索功能是否能正常使用。如果出现报错,请结合 Misskey 以及 Elasticsearch 的 log 文件检查配置文件中的信息是否正确填写或 Elasticsearch 服务是否正常启用。
当然,如果不想使用 Elasticsearch 所创建的默认管理员用户,也可以自己建立一个用户:
/usr/share/elasticsearch/bin/elasticsearch-users useradd <新建用户的用户名> -p <新建用户的密码> -r <新建用户的角色>
然而我对着 Elasticsearch 的文档看了半天,也不知道该给新建立的用户分配什么角色才能让 Misskey 正常建立并使用引索。直接给 Admin 角色当然可以正常使用,但这样又和使用默认管理员用户有什么区别呢?同时我也没找到备份 Elasticsearch 数据或者让 Misskey 手动重新建立引索的方法。这也就意味着服务器迁移后,曾经的推文内容都无法出现在搜索结果里了。原谅我智商不够,真的看不懂 Elasticsearch 的文档,我尽力了。
最后介绍一下如何备份 Misskey 的数据。Misskey 的重要数据其实只有两个部分:数据库以及用户所上传的附件目录。你可以使用任何备份程序如 Rclone 来备份这两样东西。如果你已经为你的 Misskey 实例配置了对象存储,那么就只需要备份数据库即可。因为在上文中我已经启用了 AWS 对象存储,所以为了偷懒,我就直接使用 AWS CLI 配合脚本来备份 Misskey 的数据库了。
首先安装 AWS CLI:
apt install awscli
配置 AWS 账户信息:
aws configure
跟着程序的提示输入你所使用的 IAM 账户的 ID、密钥、可用区以及输出格式。
随后建立备份目录并赋予所需的目录权限:
mkdir -p /home/backup/misskey
chmod 777 /home/backup/misskey
创建备份脚本:
/home/backup/misskey/misskeybackup.sh
备份脚本示例如下,数据库名及存储桶名等参数请根据实际需求修改:
#!/bin/bash
su - postgres << EOF
pg_dump -Fc > /home/backup/misskey/misskey-backup-$(date +%Y-%m-%d).dump
exit
EOF
aws s3 cp /home/backup/misskey/misskey-backup-$(date +%Y-%m-%d).dump s3://eric2369/misskey-backup/misskey-backup-$(date +%Y-%m-%d).dump
rm -f /home/backup/misskey/misskey-backup-$(date -d 'last month' +%Y-%m-%d).dump
exit 0
赋予备份脚本执行权限:
chmod +x /home/backup/misskey/misskeybackup.sh
建立备份服务:
vim /etc/systemd/system/misskeybackup.service
备份所用的 Systemd 服务配置文件示例如下:
[Unit]
Description=Misskey backup
[Service]
Type=simple
ExecStart=/usr/bin/bash /home/backup/misskey/misskeybackup.sh
StandardOutput=append:/home/backup/misskey/misskeybackup.log
StandardError=append:/home/backup/misskey/misskeybackup.log
TimeoutSec=60
建立备份服务所用的计时器:
vim /etc/systemd/system/misskeybackup.timer
下方给出示例中的设定是每天中午十二点进行备份,请根据实际需求进行修改:
[Unit]
Description=Misskey backup daily
[Timer]
OnCalendar=*-*-* 12:00:00
[Install]
WantedBy=timers.target
启用该备份服务:
systemctl enable misskeybackup.timer
这样每天中午十二点就会执行 `/home/backup/misskey/misskeybackup.sh` 这个脚本,将 Misskey 数据库导出为当天日期作为文件名的 dump 文件至 `/home/backup/misskey` 目录内并上传到 AWS 存储桶,同时会删除一个月前的本地备份文件。
如果需要还原 Misskey 数据库,只需要执行如下指令:
pg_restore -C -d postgres <需要还原的备份文件文件名>.dump
另外,使用纯手动搭建 Misskey 的一个好处是,在需要升级 Misskey 的时候可以做到无缝升级。当你需要升级时,首先切换到 misskey 用户
su - misskey
然后进入 Misskey 的程序目录:
cd misskey
拉取最新的 Misskey 代码:
git pull
更新子模块:
git submodule update --init --recursive
安装新的依赖并重新编译:
yarn install
NODE_ENV=production yarn build
最后重启 Misskey 服务即可:
systemctl restart misskey
这样便完成了 Misskey 的升级。