从源码以白名单模式部署Mastodon 4.x站点

从源码以白名单模式部署Mastodon 4.x站点


这篇文章是在2C 4G Debian 11 x64下部署的,此时的mastodon版本为4.1.0。

以下命令均以一个非root但具有sudo权限的用户的身份执行。如果你想为Mastodon单独创建一个用户(此处用户名为mastodon),请执行:

sudo adduser --disabled-login mastodon

这个用户不需要sudo权限,因此,为系统安装软件包是,请切换至root用户(或为root用户再单开一个shell)

一、准备环境

1. 保持系统最新、安装必要软件包

sudo apt update
sudo apt upgrade
apt install -y curl wget gnupg apt-transport-https lsb-release ca-certificates

2. 安装Node 16.x

以下方法二选一:

(1)若要多版本共存,可使用Node版本管理工具,此处使用nvm:

(如果你为mastodon创建了专门的用户,此处记得用sudo su - mastodon切回mastodon用户)

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
nvm install --lts=gallium
nvm use lts/gallium
node -v

(2)直接添加apt源并安装:

sudo curl -sL https://deb.nodesource.com/setup_16.x | bash -
sudo apt update
sudo apt install node

3. 安装Postgresql和Redis

sudo wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list
sudo apt update
sudo apt install postgresql redis-server

4. 补充安装Mastodon文档要求的其它包

sudo apt update
sudo apt install -y \
 imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core \
 g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf \
 bison build-essential libssl-dev libyaml-dev libreadline6-dev \
 zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev \
 nginx redis-server redis-tools postgresql postgresql-contrib \
 certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev

5. 安装Yarn

npm install --global yarn
corepack enable
yarn set version classic

6. 安装Ruby

此处直接采用官方文档中的版本管理方案,不再另外列出其它方案。如果你为mastodon创建了单独的用户,这一步需要切回mastodon用户操作。

cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec bash
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4
rbenv global 3.0.4
gem install bundler --no-document

7. 创建数据库用户

sudo -u postgres psql

在输入下面的SQL语句时,请注意替换对应的用户名及密码。

CREATE USER mastodon PASSWORD 'XXXXXXX' CREATEDB;
\q

二、部署Mastodon

如果你创建了单独的用户,此步需切至mastodon用户操作。

1. 拉取源码存储库

git clone https://github.com/mastodon/mastodon.git live && cd live
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

2. 安装依赖

bundle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN)
yarn install --pure-lockfile

3. 生成配置

RAILS_ENV=production bundle exec rake mastodon:setup

按提示输入即可。这一步生成的是.env.productions文件,可参考下面内容交互式填写:注意,下面的内容仅列出rake mastodon:setup命令要求输入的内容

LOCAL_DOMAIN=xxx.closed.social # 本站域名
SINGLE_USER_MODE=false   # 不启用单用户模式
DB_HOST=/var/run/postgresql   # 保持默认即可,除非你改过
DB_PORT=5432    # 保持默认即可
DB_NAME=closed_social   # 自行起名
DB_USER=mastodon   # 与(一)中第7步用户名一致
DB_PASS=XXXXX   # 与(一)中第七步密码一致
REDIS_HOST=localhost # 保持默认即可
REDIS_PORT=6379 # 保持默认即可
REDIS_PASSWORD= # 留空即可
S3_ENABLED=false # 暂不配置s3
SMTP_SERVER=smtp.xxx.xxx # SMTP服务可选择126/163/QQ等免费邮箱、腾讯企业邮箱(要求域名备案、有免费计划)、阿里云邮件服务(要求发件域名备案)等
SMTP其余配置根据个人情况填写
SMTP_AUTH_METHOD=plain # 默认值
SMTP_OPENSSL_VERIFY_MODE=peer # 默认值
SMTP_ENABLE_STARTTLS=auto # 默认值
SMTP_FROM_ADDRESS='闭社xx站 xxx@xxx.xxx' # 发件人名称不要含有特殊字符

这一步会提示创建管理员用户,请记下用户名和生成的初始密码。


【排错】如果连接数据库时遇到connection closed by peer之类的问题,请以root权限修改 /etc/postgresql/15/main/pg_hba.conf ,将其中Unix套接字的认证连接方式从peer改为scram-sha-256

# 更改前
local   all all   peer
# 更改后
local   all all   scram-sha-256

然后

systemctl restart postgresql

4. 生成SSL证书

如果你使用closed.social域名,你需要联系域名所有者,如果你使用自己的域名,则可以按照自己觉得合适的方式生成。

免费证书推荐使用acme.sh:https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E

5. 配置反代

此处使用Nginx,如果服务器还未安装Nginx,可直接从apt安装或添加第三方打包源后安装。Nginx安装过程略。

# 请把“/home/mastodon/live”替换为你拉取的Mastodon源码的绝对路径。
sudo cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
sudo ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon

编辑/etc/nginx/sites-available/mastodon:编辑要点:

(1)如果你修改了masdon web或streaming API的监听端口,请修改nginx文件中对应的upstream:

(2)注意修改两个server的server_name字段和root字段,server_name字段是你站点的域名,root字段是拉取的mastodon源码的绝对路径下的public目录。

(3)注意修改ssl_certificate和ssl_certificate_key字段为你的证书所在绝对路径,并确保Nginx所在的用户/用户组(均为www-data)对其具有读权限。

编辑完成后测试Nginx配置:

sudo nginx -t

无误后重启Nginx(因为需要加载新证书)

sudo systemctl restart nginx

6. 配置Systemd服务、启动Mastodon

请把“/home/mastodon/live”替换为你拉取的Mastodon源码的绝对路径。

cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/

请提前配置EDITOR变量或将其替换为你喜欢的编辑器

$EDITOR /etc/systemd/system/mastodon-*.service

编辑要点:

(1)每个文件的的User字段均要改为mastodon源码目录的所属用户,或你专门为mastodon新建的用户。

(2)每个文件的WorkingDirectory和ReadWritePaths(如果有)字段均要改为mastodon源码所在的绝对路径

(3)如果你要指定不同的监听端口,请修改对应的环境变量字段

(4)ExecStart字段中ruby运行环境的位置应修改为对应的用户(即:位置不一定是/home/mastodon/...)

启动并配置开机自启:

systemctl daemon-reload
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming

如遇报错,可使用journalctl查找原因

三、配置Mastodon

1. 登录并修改管理员密码

这一步要求你的SMTP配置可用,如果你的SMTP还没配好,请到文档中寻找通过命令行修改密码的方法(可能只有重置密码的命令,我没有细看)。

2. 载入注册邮箱白名单及附加配置

在 .env.production 文件后酌情添加以下配置:

# 必须添加
# 1. 注册邮箱白名单
EMAIL_DOMAIN_ALLOWLIST=xxx.edu.cn|xiaoyou.xxx.cn|jiaozhigong.xxx.edu.cn
# 2. 白名单模式(仅与指定实例互动)
LIMITED_FEDERATION_MODE=true

# 可选配置
# 1. 实例默认语言
DEFAULT_LOCALE=zh-CN
# 2. 信任的反代IP(此处的配置包含了常用本地段及所有Cloudflare IP段)
# 配置这个可以在后台看到真实用户IP
# 如果你在本地用Nginx等进行反代后又套了一层Cloudflare反代,那么你可能还需要在Nginx里配置Cloudflare的IP段为信任代理源
TRUSTED_PROXY_IP=127.0.0.1/8,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7,173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32
# 3. Redis命名空间
# 如果你的redis中还存在其它项目,请使用
REDIS_NAMESPACE=mastodon_xxx

完成后,在Mastodon源码所在目录执行:

RAILS_ENV=production ./bin/tootctl domain purge --limited-federation-mode

然后重启所有mastodon服务。

3. 联动闭社实例

这里给出一份截止到目前的闭社实例列表:

#domain
thu.closed.social
tha.closed.social
sjtu.closed.social
umas.social
fzu.closed.social
mku.social
njust.club
s.ourneu.space
smu.closed.social
bjut.closed.social
zzuli.closed.social
nwpu.closed.social
uestc.social

可以将其保存为一个文本文档,然后在首选项-运营-已知实例中导入。也可以逐个添加。

当你方实例和对方实例均添加完毕后,可主动搜索对方实例管理员账号,发送私信制造跨站联动。如果这些操作均能成功,就证明实例间可以正常通信。

4. 其它调优

(1)本机安全配置

建议关闭SSH密码登录(改为密钥登录)、安装防火墙并配置防火墙规则。还可以更改SSH端口。

(2)Postgres性能调优

参考官方文档给出的工具:https://pgtune.leopard.in.ua/#/

(3)开放部分API

目前版本中,LIMITED_FEDERATION_MODE禁用了对所有api的公开访问。这导致两个主要问题:

  1. 访问主页会报一堆401错误
  2. 部分APP登录会出现登陆失败或识别不出实例的情况

可尝试如下解决方案:

  1. 首先在网页端正常登录,或用其它方式拿到Mastodon的AccessKey
  2. 在浏览器或命令行中请求如下接口,将返回值分别保存至文件中:
https://your.domain/api/v1/instance
https://your.domain/api/v2/instance

3. 编辑Nginx对应站点文件,添加如下伪静态规则:

 location /api/v1/instance {
   alias /path/to/v1_instance.json;
 }
 location /api/v2/instance {
   alias /path/to/v2_instance.json;
 }

重载nginx,即可基本解决问题。

这个方法的缺陷在于:无法实时更新实例人数。

另外,访问站点主页时还有两个API会报错,分别是/api/v1/trend/tags/ 和 /api/v1/instance/extended_description 。 理论上可参照此方法进行修改。

(3)S3

很多S3服务商为流量计价,如果有人恶意刷流量,可能会造成天价账单。
此处给出Cloudflare R2的S3配置,开通Cloudflare R2需要外币卡,但其仅按请求计费且提供10G免费额度,足够站点初期使用,速度方面尚可。

# 修改 .env.production
# 修改内容
S3_ENABLED=true

# 新增内容
S3_ALIAS_HOST=你的存储桶绑定的域名,可省略但建议配置
S3_BUCKET=存储桶名
S3_ENDPOINT=https://<你的cloudflare账户ID>.r2.cloudflarestorage.com/
AWS_ACCESS_KEY_ID=在R2 API页面生成的Access Key
AWS_SECRET_ACCESS_KEY=在R2 API页面生成的Access Secret
S3_PROTOCOL=https
S3_PERMISSION=private

 (4)CDN

直接回源源站并配置Access-Control-Allow-Origin头即可,也可手动将Mastodon源码内的Public文件夹托管至服务商,例如上传至另一个S3存储桶并绑定域名。

然后修改 .env.production

CDN_HOST=CDN域名

重启Mastodon的Web服务。

更新后不要忘了刷新CDN。

(5)Elasticsearch

Elasticsearch的部署效果是能为站点带来全文搜索,缺点在于内存开销巨大,请根据机器配置自我权衡。笔者目前没有配置,此处给出官方文档的配置步骤。

配置环境:

sudo apt install openjdk-17-jre-headless

sudo wget -O /usr/share/keyrings/elasticsearch.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch

sudo echo "deb [signed-by=/usr/share/keyrings/elasticsearch.asc] https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list

sudo apt update

sudo apt install elasticsearch

sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch

安装两个中文分词插件:参见:

https://github.com/medcl/elasticsearch-analysis-ik#install

https://github.com/medcl/elasticsearch-analysis-stconvert/releases

安装完成后重启elasticsearch


编辑 .env.production:

ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200

# 可选配置
ES_USER=你在elasticsearch中的对应用户
ES_PASS=用户密码
ES_PREFIX=默认值跟随redis的命名空间前缀,可不管

修改索引相关代码:(如果你安装了中文分词)

参见:https://docs.joinmastodon.org/admin/optional/elasticsearch/#chinese-search-optimization


重启受影响服务:

sudo systemctl restart mastodon-sidekiq
sudo systemctl reload mastodon-web

创建索引:(如果你创建了专门的用户,请切回对应用户)

在mastodon源码目录执行:

RAILS_ENV=production bin/tootctl search deploy

Report Page