This page looks best with JavaScript enabled

Misskey | 利用Docker-compose搭建Fedi开源社交平台

功能复杂UI可爱的分布式SNS

 ·  ☕ 12 min read

简要介绍

众所周知,简中互联网内开源Fedi社区相当小众,但即便如此,Mastodon的用户依旧是相当庞大的,而同为联邦宇宙软件一员的Misskey则是小众中的小众。

实际上中文长毛象社区由于各种不可说原因经历了几次搬迁潮,再加上象友们的安利邀请,最终形成了现在的盛况。也有人觉得Mastodon(长毛象)UI界面比较好看,再加上几位知名站长的个性化魔改&稳定维护和Mastodon自带的搬家功能,即使长毛象目前仅支持纯文本发嘟,受众依旧相当多,很多人以为联邦宇宙指的就是Mastodon本身了。

然而从站长角度来说,Mastodon可以称得上资源占用怪,相比Misskey来说Mastodon实在是heavy很多,这是因为Mastodon用的Ruby来写的,Misskey用的TypeScript(JS)来写的,运行上来说Misskey的速度和运存占用相对占优势。另外,Misskey是不需要邮件服务的,这意味着用户需要牢记自己的密码。

Misskey是日本开发者syuilo基于Fediverse开发的一个去中心化社交平台,可以与Mastodon互通,且拥有一些Mastodon没有的复杂小玩意(毕竟源自霓虹嘛)。虽然官方文档写得真的很烂,而且是个人项目,但Misskey本身确实是个好东西,而且由于有公司资金支持,近期更新非常频繁。相比于Mastodon,Misskey更适合搭建个站。

搭建过程

2021年了官方教程居然在推荐自行build镜像。虽然说也不是不行但对小型服务器的压力太大了,而且Dockerhub中已经有官方推送的Misskey镜像,所以直接使用就好。

另外我发现如果使用Debian系统按照官方文档来搭建,会遇到一些问题:

但是用debian系统会有很多问题,比如不能上传附件,smtp和对象存储全都出错,新用户不能注册,反正问题多多就是了。后来我发现是node.js原因,misskey最好用16版本号的node.js。
debian系统下安装misskey前先安装node.js。

详见这篇文章

运行以下命令解决:

sudo curl -fsSL https://deb.nodesource.com/setup_16.x | sudo bash -
sudo apt install nodejs
注意:
本教程省略了一些与Docker&Docker compose相关的知识。如果没有安装,请参考这里安装。本教程使用Debian 10。

在任意目录下新建docker-compose.yml文件:

cd /opt && mkdir misskey && cd misskey
nano docker-compose.yml

文件内容如下:

version: "3"

services:
  web:
    restart: always
    image: misskey/misskey:latest
    links:
      - db
      - redis
    ports:
      - "127.0.0.1:3000:3000"   #如果服务器端口3000已被使用,可改为其他端口,例如127.0.0.1:5210:3000
    networks:
      - internal_network
      - external_network
    volumes:
      - ./.config:/misskey/.config
      - ./files:/misskey/files  #用户上传到本地的文件,如果您一开始就接入外部存储(如wasabi或是AWS S3)您可以忽略这块配置


  redis:
    restart: always
    image: redis:latest
    networks:
      - internal_network
    volumes:
      - ./redis:/data

  db:
    restart: always
    image: postgres:12.2-alpine
    networks:
      - internal_network
    env_file:
      - .config/docker.env
    volumes:
      - ./db:/var/lib/postgresql/data

networks:
  internal_network:
    internal: true
  external_network:

新建配置文件夹.config

mkdir .config
cd .config

运行nano default.yml新建default.yml,复制官方项目的example.yml内容,回到服务器中粘贴,部分改动如下:

  • url项改为你的域名。由于分布式属性,一旦开启站点则不可更改。
  • 确保port: 3000这一行取消注释,端口号不用更改。
  • dbRedishostlocalhost分别改为dbredis
  • db项的userpass改为你想设置的数据库用户和数据库密码。
  • 如有ActivityPub协议连通性需求(例如与Mastodon站点互动)需要开启signToActivityPubGet: true选项(默认关闭),位置在文件末尾部分。

保存。

运行nano docker.env新建docker.env,复制官方项目的docker_example.env内容,回到服务器中粘贴,将POSTGRES_USERPOSTGRES_PASSWORD改为刚刚自己设置的数据库用户和数据库密码。

回到上级目录,初始化数据库:

cd ../
docker-compose run --rm web yarn run init

启动容器使站点上线:

docker-compose up -d

Nginx反向代理

首先去DNS服务商添加一条指向服务器ip,内容为域名的A记录,然后回到服务器运行以下命令:

sudo -i   #切换至root用户
apt install nginx -y    #安装nginx
apt install snapd
snap install core   #安装snap
snap install certbot --classic  #使用snap安装certbot

运行nano /etc/nginx/conf.d/misskey.conf,内容如下:

# Sample nginx configuration for Misskey
#
# 1. Replace example.tld to your domain
# 2. Copy to /etc/nginx/sites-available/ and then symlink from /etc/nginx/sites-enabled/
#    or copy to /etc/nginx/conf.d/

# For WebSocket
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=cache1:16m max_size=1g inactive=720m use_temp_path=off;

server {
    listen 80;
    listen [::]:80;
    server_name 你的域名;

    # For SSL domain validation
    root /var/www/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 你的域名;
    ssl_session_cache shared:ssl_session_cache:10m;

    # To use Let's Encrypt certificate
    #ssl_certificate     /etc/letsencrypt/live/你的域名/fullchain.pem;
    #ssl_certificate_key /etc/letsencrypt/live/你的域名/privkey.pem;

    # To use Debian/Ubuntu's self-signed certificate (For testing or before issuing a certificate)
    #ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    #ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    # SSL protocol settings
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA;
    ssl_prefer_server_ciphers on;

    # Change to your upload limit
    client_max_body_size 80m;

    # Proxy to Node
    location / {
        proxy_pass http://127.0.0.1:3000;   #需要与docker-compose.yml中端口配置一致,例如http://127.0.0.1:5210
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_redirect off;

        # If it's behind another reverse proxy or CDN, remove the following.
        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;

        # For WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Cache settings
        proxy_cache cache1;
        proxy_cache_lock on;
        proxy_cache_use_stale updating;
        add_header X-Cache $upstream_cache_status;
    }
}

ablobcouncil 注意:
本文中misskey.conf文件已过时,请至官方文档查看最新版本。

测试配置文件是否有错误(试运行):

nginx -t

若没有错误,生效新的配置文件并运行 Nginx,开机启动:

nginx -s reload
systemctl start nginx
systemctl enable nginx

运行sudo certbot --nginx获取SSL证书。

注册管理员帐号

访问你的域名注册一个帐号,此帐号会被设置为管理员。

可以将普通权限帐号升级为管理员。参考这个issue,在服务器中运行docker-compose run --rm web node packages/backend/built/tools/mark-admin @用户名(路径可能有变动),注意需要先注册才行。

媒体文件外部存储

参考salt站长部署媒体文件外部存储服务。以Scaleway为例进行配置,使用其他s3存储服务请查找官方文档及相似文章。

注册帐号、新建Project&储存桶以及获取API key的具体步骤请看参考文章,没有难度,本文不再赘述。但需要注意的是,储存桶名要填写媒体服务子域名,例如im.yourdomain.com

同步已有媒体

关于这一步,我发现Misskey和Mastodon的存储策略不同,即使将files文件夹下的媒体文件同步到S3桶中也无法使用媒体文件。因此如果你曾经将媒体文件存储在服务器本地,日后备份迁移时files文件夹一定要备份。除非在网页端配置好对象存储之后将之前的图片手动上传到网盘然后再删除旧图片,否则没有办法将files目录下的文件同步到S3并正常使用。

开启对象存储

打开DNS解析商,以cloudflare为例。添加一项名称为子域名(例如im.yourdomain.com),目标为im.yourdomain.com.s3.fr-par.scw.cloud(其中fr-par需要按照储存桶地址更改为nl-amspl-waw)的CNAME记录,并开启cloudflare的代理。

使用管理员帐号登录并打开Misskey控制面板,下拉菜单找到Object Storage (物件儲存),打开开关开始设置:

  • BaseURL:你的子域名,带通讯协议,例如https://im.yourdomain.com
  • Bucket:你的子域名,和储存桶名相同,例如im.yourdomain.com
  • Prefix:留空即可
  • Endpoints3.fr-par.scw.cloud/s3.nl-ams.scw.cloud/s3.pl-waw.scw.cloud
  • Region:储存桶地区,填写fr-par/nl-ams/pl-waw
  • ACCESS KEY:填写在Scaleway获取的Access key
  • SECRET KEY:填写在Scaleway获取的Secret key

打开SSL(声明Endpoint使用HTTPS),关闭媒体代理,打开public-read,打开s3ForcePathStyle,保存。上传一张图片,若发note没有出现问题且图片清晰,则部署成功。

开始食用

Misskey和Mastodon的中继是通用的,尽情探索你的站点吧!

最后附上Misskey最大最知名实例Misskey.io的介绍:

Misskey.ioは、地球で生まれた分散マイクロブログSNSです。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。
暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。

后续设置

防止被搜索引擎爬取

参考Misskey 防搜索引擎抓取一文。

就像参考文章里所说的,Misskey默认的robots.txt不阻止任何搜索引擎爬取页面。在搭建Misskey之前我也多次在Google搜索公开旧嘟文内容时顺着Misskey站点的tag页面找到,很难不心慌。

站点的robots.txthttps://yourdomain.com/robots.txt下,默认配置是:

user-agent: *
allow: /

# todo: sitemap

此配置允许搜索引擎搜索任何内容。robots.txt的源码位于Misskey项目下的/packages/backend/assets/robots.txt。可以直接修改此文件,或是添加Nginx规则。

运行nano /etc/nginx/conf.d/misskey.conf,在最后一个花括号前加上:

    location =/robots.txt {
        default_type text/html;
        add_header Content-Type "text/plain; charset=UTF-8";
        return 200 "User-agent: *\nDisallow: /\n";
    }

并直接运行systemctl restart nginx重启Nginx即可生效。生效后查看robots.txt,内容变为:

User-agent: *
Disallow: /

但实际上修改robots.txt也并不能完全保证不被搜索引擎抓取。当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。

Robots协议是国际互联网界通行的道德规范,基于以下原则建立:

  1. 搜索技术应服务于人类,同时尊重信息提供者的意愿,并维护其隐私权;
  2. 网站有义务保护其使用者的个人信息和隐私不被侵犯。

如果搜索引擎不遵守约定的Robots协议,那么通过在网站下增加robots.txt也是不起作用的,它只是一个“君子协定”,并不是实质性的保证。

若想禁止特定的user-agent(即用户代理),可以修改Misskey的Nginx配置文件,这里举个例子:

    if ($http_user_agent ~* (2345|360|ali-|alipay|archive|baidu|bingbot|bytespider|coolnovo|duckduckgo|easou|facebook|google|huaweibrowser|iaskspider|iqiyi|jike|lbbrowser|liebao|maxthon|meizu|metasr|micromessenger|miui|miuibrowser|msnbot|oneplus|oppo|qihoo|qiyu|qq|saayaa|se\ 1.x|se\ 2.x|sina|sogou|soso|taobao|taobrowser|tencent|teoma|the\ world|twitter|ucweb|vivo|wechat|weibo|xiaomi|yahoo|yandexbot|yisou|yodao|youdao|zte)) {

        return 403;
   
    }

其中~表示不区分大小写。

若站点开启了cdn如Cloudflare(即打开Proxy小橙云),则可以建立防火墙规则:屏蔽受审查的浏览器/设备,满足条件即封锁/质询即可。此规则来自wxw管理员,感谢ta。

开启bot防护

实际上就是注册时检查你是否是人类,可以选择Google的reCAPTCHA(v2/v3)或是hCaptcha。二者都有免费方案配置也非常简单,介绍一下hCaptcha的使用方式。

首先注册hCaptcha并选择免费方案,随后网页跳转到以下页面:

复制这两个密钥粘贴到Misskey管理控制台即可。

Service Worker设置

参考Misskeyインスタンスで最初に設定するべきインスタンス設定とその他設定の説明一文。

开启后将站点设置为PWA应用(安装到桌面)即可收取消息推送。还是能提高使用体验的,推荐一试。

开启此功能需要生成一对公私钥,在任何一台服务器中都可以生成。

Linux运行:

npx web-push generate-vapid-keys

或是使用Docker生成密钥对:

docker run --rm node npx web-push generate-vapid-keys

刚刚发现一个网站可以在线生成VAPID密钥对,不会有什么安全隐患。如果不想使用服务器的话可以直接在线生成:VAPID Key Generator

将生成的密钥对填入Misskey管理控制台即可。不过在实际使用时如果因为网络问题没有及时刷新页面,PWA应用会白屏并显示Offline. Service Worker @12.118.1,此时强制刷新即可恢复。

关于Misskey使用上的小问题

媒体文件的存储

Misskey的策略是只存储站内用户的媒体资源,使用的策略是网盘,所有内容保存在files目录下。上传任意文件至网盘之后,发帖文的时候可以随时引用文件!而Mastodon如果要在不同嘟里发同一张图得上传两次。当然也可以选择缓存外站用户的媒体(缩略图),相关所有操作都在控制面板->常规设置里。

另外需要注意的是,Misskey上传媒体文件的时候会保留图片中记录的设备、位置还有文件名等等敏感信息,真正意义上的原图上传。而Mastodon上传过程中会给文件重命名,并且去掉图片中包含的敏感信息。对于想要保护个人隐私的朋友这里一定要注意一下。

Misskey的站点维护

不像Mastodon有功能极为丰富的tootctl命令集,Misskey几乎是用网页端就能完全控制你的站点。Misskey也有一个CLI命令,就是那个把普通用户标记成管理员的命令,官方文档有提到。但Misskey是个年轻的项目,路径变动比较频繁,可能用不了。

删除旧数据的操作使用的是docker命令docker system prune,该命令用来清理没有使用的数据,包括那些已停止的容器、dangling镜像(未被任何镜像引用的镜像)、未被容器引用的network和构建过程中的cache。

对于升级操作,一般来说只要:

docker-compose down   #关闭Misskey
docker pull misskey/misskey:latest   ##拉取最新镜像
cp -r db db1   #备份数据库,防止升级过程翻车。待站点重启确认无问题后运行rm -rf db1删除备份即可
docker-compose up -d   #重启Misskey
docker rmi -f  `docker images | grep '<none>' | awk '{print $3}'`    #删除旧镜像

修改默认字数限制

应该是在https://github.com/misskey-dev/misskey/blob/develop/packages/backend/src/const.ts#L1。目前Misskey的默认字数是3000字,并且不考虑将默认字数上限放到网页端控制面板或者配置文件中,详见这个issue

Elasticsearch(ES搜索)

不像Mastodon的搜索那么鸡肋必须靠ES才能正常使用,Misskey默认的搜索就足够使用了。而且对于小站点来说,开了ES很耗费内存,性价比不高。如果默认搜索出了问题,可以重建Misskey数据库的索引,相当于磁盘碎片整理。具体操作应该是:

docker-compose down 
cp -r db db1   #备份数据库
docker-compose up -d db
docker exec -it db psql -U postgres   #进入容器。若报错数据库用户postgres不存在,则换成Misskey的数据库用户
REINDEX DATABASE Misskey数据库名   #重建数据库索引
\q   #回车退出容器
docker-compose up -d

附上可以参考的帖子


Roelxy
WRITTEN BY
Roelxy
新世紀摸魚戰士