Mastodon是一个基于ActivityPub协议的联邦式微博客类软件,可以搭建自己的实例并与其他实例互相连接,每个实例都可以有不同的主题要求或规定,此外也可以和其他使用ActivityPub协议的站点,诸如Pleroma、Misskey等互通。
为了方便起见,Kubernetes使用K3s发行版部署。此外,如果有大量媒体内容,则建议使用对象存储以避免挤占服务器存储空间,以及如果想对外开放注册还需要电子邮件发件代理。
Mastodon官方提供了一个使用Helm部署的存储库,但由于该库使用了Bitnami的Helm存储库提供依赖组件,而Bitnami目前尚不支持Arm架构,且看起来也没什么意愿,所以如果需要在arm64架构的服务器中部署则需要分别部署依赖组件。这里将分别提供两种部署的方法。Bitnami现在已经提供ARM架构容器镜像。需要注意的是用于全文检索功能的ElasticSearch会大量消耗内存,如果内存低于8G可能需要修改设置来降低内存占用、换用OpenSearch,或者干脆换其他资源占用更低的ActivityPub协议服务端。
更新:官方helm源有些改动,以下values.yaml文件的内容可能并未完全覆盖所有必须内容。
准备工作
安装K3s
K3s支持跨架构,所以这里在两种架构中都使用同样的方法安装。
如果使用的是RHEL系发行版,需要先关闭firewalld,不然会导致pod间无法通信,当然如果精通防火墙配置也可以编辑防火墙设置来放行。
sudo systemctl disable firewalld --now
安装K3s时如果打算从集群外的设备来控制集群,推荐在安装命令中使用--tls-san参数来为kubeconfig文件中的证书添加域名或外部IP,反之则使用默认的安装命令即可:
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--tls-san 域名或IP" sh -s -
如果在控制节点控制集群时,非root用户遇到kubeconfig文件无访问权限的情况,使用以下方法将文件复制出来并获得权限:
sudo cp -i /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
最后在.bashrc
文件最后一行添加环境变量:
export KUBECONFIG=$HOME/.kube/config
保存后使用bash
命令刷新即可。
从外部控制时,首先放行6443端口,然后将kubeconfig复制到外部设备,修改文件内的服务器地址。使用时在kubectl或helm后面添加--kubeconfig 文件路径
,后面再写其他命令即可,也可以直接修改环境变量来设置为默认。
安装cert-manager
开启https访问需要申请证书,通常使用cert-manager管理,这里使用Helm来安装,首先Helm需要安装在可以控制集群的设备中。可以使用脚本或包管理器安装Helm。
添加存储库:
helm repo add jetstack https://charts.jetstack.io && helm repo update
安装cert-manager:
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true
使用yaml文件创建ClusterIssuer,这里使用HTTP-01方式,需要外部可以访问80和443端口,如无法访问则需使用DNS-01方式:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: "letsencrypt"
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: traefik
保存后使用kubectl apply -f yaml
命令来应用。此时颁发证书的准备已经完成,而正式的证书申请在创建Ingress时进行。
使用SendGrid作为发件代理
开放外部注册需要配置电子邮件发送功能来进行账号验证,这里以SendGrid为例。
首先注册Sendgrid,如果验证迟迟无法通过可以联系客服提供社交账号。注册后验证发件使用的域名,在账户管理中左侧选择Settings中的Sender Authentication,然后选择Authenticate Your Domain,根据提示设置DNS即可。
验证后创建SMTP Relay发件代理,选择左侧Email API中的Integration Guide,然后选择SMTP Relay,此时会提醒创建API Key,创建完成后妥善保存,之后会将其配置到Mastodon中。创建后需要发送一个电子邮件来通过测试才能正式激活,可以参照SendGrid说明使用Telnet发送。
使用Oracle对象存储来保存媒体文件
由于媒体文件会大量占用存储空间,所以推荐使用更为廉价的对象存储来保存。如果服务器磁盘够大的话也可以不用。
在Oracle Cloud里面选择存储里面的存储桶,然后创建存储桶,记下填写的名称,其他的使用默认设置即可,然后选择右上角的用户菜单中的“租户: 用户名”,进入租户详细信息界面后,如果Amazon S3 兼容性 API 指定的区间为空则选择编辑对象存储设置,将其设置为根区间。然后记录下对象存储名称空间的内容。
接下来选择右上角用户菜单中的“我的概要信息”,选择左下角的客户密钥,然后生成密钥,保存好生成的密钥,保存后在密钥列表中还有一个访问密钥也一并保存好。
最后在Oracle文档中查找区域标识符,当前账户的地区在管理界面的最上方可以找到,此外有一个简单的方式时直接在管理界面的URL中找到region=
,后面就是区域标识符。
将区域标识符和对象存储明明空间组合进URL中:
https://<对象存储名称空间>.compat.objectstorage.<区域标识符>.oraclecloud.com
即可得到访问Oracle对象存储的地址。保存好地址和两个密钥,之后会配置到Mastodon中。
生成Mastodon的必须密钥
运行Mastodon还需要用于浏览器会话、两步验证和推送的密钥,这些密钥需要通过Mastodon镜像来生成。这里分别提供使用docker和kubectl的命令。
首先生成用于浏览器会话的密钥secret_key_base
和用于两步验证的密钥otp_secret
。将以下命令运行两次,在输出中即可得到所需的密钥。
docker run --rm -it tootsuite/mastodon:latest bundle exec rake secret
kubectl run -it --rm mastodon --image=tootsuite/mastodon --command bundle exec rake secret
然后使用以下命令生成用于推送通知的密钥vapid_private_key和vapid_public_key,这次一个命令中的输出即可得到公钥和私钥。
docker run --rm -it tootsuite/mastodon:latest bundle exec rake mastodon:webpush:generate_vapid_key
kubectl run -it --rm mastodon --image=tootsuite/mastodon --command bundle exec rake mastodon:webpush:generate_vapid_key
至此准备工作完成。
使用Helm Chart部署所有组件(仅限x86架构)
在x86服务器中部署较为简单,只要使用官方提供的Helm Chart包即可
首先将Mastodon Chart存储库克隆到本地:
git clone https://github.com/mastodon/chart.git
然后进入到目录中修改values.yaml文件,由于文件很长,这里分块修改,并且不会修改所有配置,如果需要修改其他配置,可以参考注释或查看官方文档。
首先修改mastodon区块,其中的createAdmin用于创建默认管理员用户,将其设为开启并按需修改:
createAdmin:
# @ignored
enabled: true
# @ignored
username: 管理员用户名
# @ignored
email: [email protected]
然后修改地区和域名,可用的locale
可以在文档中找到。local_domain
为用户名后面的服务器识别域名,web_domain
为网站本身的域名,如果使用同一个则可以只设置local_domain
,另一个设置为null
。此外如果不同的话还需要在web服务器中配置重定向,将local_damain/.well-known/webfinger
跳转到web_domain/.well-known/webfinger
。
locale: zh-CN
local_domain: mastodon.local
# -- Use of WEB_DOMAIN requires careful consideration: https://docs.joinmastodon.org/admin/config/#federation
# You must redirect the path LOCAL_DOMAIN/.well-known/ to WEB_DOMAIN/.well-known/ as described
# Example: mastodon.example.com
web_domain: null
# -- If set to true, the frontpage of your Mastodon server will always redirect to the first profile in the database and registrations will be disabled.
接下来添加对象存储设置,使用对象存储首先需要设置为开启,然后将之前的地址和两个私钥,以及存储桶名称填入其中:
s3:
enabled: true
access_key: "访问密钥"
access_secret: "私钥"
# -- you can also specify the name of an existing Secret
# with keys AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
existingSecret: ""
bucket: "存储桶名称"
endpoint: "https://URL地址"
hostname: "URL主机名,没有https"
region: "区域标识符"
# -- If you have a caching proxy, enter its base URL here.
alias_host: ""
配置会话、两步验证和推送的密钥:
secrets:
secret_key_base: "会话密钥"
otp_secret: "两步验证密钥"
vapid:
private_key: "推送私钥"
public_key: "推送公钥"
# -- you can also specify the name of an existing Secret
# with keys SECRET_KEY_BASE and OTP_SECRET and
# VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY
existingSecret: ""
之后是邮件发送配置:
smtp:
auth_method: plain
ca_file: /etc/ssl/certs/ca-certificates.crt
delivery_method: smtp
domain:
enable_starttls: 'auto'
from_address: 发件地址@example.com
openssl_verify_mode: peer
port: 587
reply_to:
server: smtp.sendgrid.net
tls: false
login: apikey
password: SendGrid的API密钥
# -- you can also specify the name of an existing Secret
# with the keys login and password
existingSecret:
mastodon区块修改完成,然后修改ingress配置,由于之前设置了cert-manager,这里反注释即可使用cert-manager生成证书,然后按需修改域名即可。
ingress:
enabled: true
annotations:
# For choosing an ingress ingressClassName is preferred over annotations
# kubernetes.io/ingress.class: nginx
#
# To automatically request TLS certificates use one of the following
# kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt"
#
# ensure that NGINX's upload size matches Mastodon's
# for the K8s ingress controller:
# nginx.ingress.kubernetes.io/proxy-body-size: 40m
# for the NGINX ingress controller:
# nginx.org/client-max-body-size: 40m
# -- you can specify the ingressClassName if it differs from the default
ingressClassName:
hosts:
- host: mastodon.local
paths:
- path: '/'
tls:
- secretName: mastodon-tls
hosts:
- mastodon.local
最后为数据库和缓存设置密码:
# https://github.com/bitnami/charts/tree/master/bitnami/postgresql#parameters
postgresql:
# -- disable if you want to use an existing db; in which case the values below
# must match those of that external postgres instance
enabled: true
# postgresqlHostname: preexisting-postgresql
# postgresqlPort: 5432
auth:
database: mastodon_production
username: mastodon
# you must set a password; the password generated by the postgresql chart will
# be rotated on each upgrade:
# https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrade
password: "密码"
# Set the password for the "postgres" admin user
# set this to the same value as above if you've previously installed
# this chart and you're having problems getting mastodon to connect to the DB
# postgresPassword: ""
# you can also specify the name of an existing Secret
# with a key of password set to the password you want
existingSecret: ""
# https://github.com/bitnami/charts/tree/master/bitnami/redis#parameters
redis:
# disable if you want to use an existing redis instance; in which case the
# values below must match those of that external redis instance
enabled: true
hostname: ""
port: 6379
# -- you must set a password; the password generated by the redis chart will be
# rotated on each upgrade:
password: "密码"
# you can also specify the name of an existing Secret
# with a key of redis-password set to the password you want
# auth:
# existingSecret: ""
完成后保存,然后进入chart目录并运行:
helm dep update
来拉取数据库、缓存和全文检索的依赖组件,完成后运行
helm install --namespace mastodon --create-namespace mastodon ./ -f ./values.yaml
成功后会显示登录网址,但此时管理员账号是因为没有密码是无法登录的,可以使用邮箱进行重置,也可以使用以下命令来进入容器进行管理:
kubectl -n mastodon exec -it deployment/mastodon-web -- bash
进入后执行以下命令来重置密码:
tootctl accounts modify 管理员用户名 --reset-password
也可以合并到一条命令中:
kubectl -n mastodon exec -it deployment/mastodon-web -- tootctl accounts modify 管理员用户名 --reset-password
分别部署组件和Mastodon
首先创建命名空间:
kubectl create ns mastodon
部署PostgreSQL和Redis,这里为了方便起见仍然使用Bitnami的Chart,但将镜像替换为支持ARM架构的官方镜像。使用以下命令即可:
helm -n mastodon install postgresql bitnami/postgresql \
--set global.postgresql.auth.postgresPassword="管理员密码" \
--set global.postgresql.auth.username="用户名" \
--set global.postgresql.auth.password="密码" \
--set global.postgresql.auth.database="数据库名" \
--set image.repository="postgres" \
--set image.tag="15.0"
helm -n mastodon install redis bitnami/redis \
--set global.redis.password="密码" \
--set architecture="standalone" \
--set image.repository="redis" \
--set image.tag="7.0"
以上的密码、用户名、数据库名要和Mastodon的values.yaml文件中一一对应。运行后会返回集群内部访问的域名,诸如postgresql-postgresql.mastodon.svc.cluster.local
这样。
进入Chart目录,除了上一章中对values.yaml文件进行的修改以外,还要关闭PostgreSQL、Redis和ElasticSearch的部署,分别在230行、239行和261行,将其改为:
enable: false
然后其余诸如用户名、密码、管理员密码等则填写之前安装时设置的,hostname
则填写之前返回的域名。需要注意的是这次redis配置中的existingSecret
必须填写,通常填写redis
即可,如果做过其他改动可以使用kubectl -n mastodon get secret
列出secret来查找。
此外,除了values.yaml以外,还需要修改Chart.yaml,在依赖项中最后添加:
- name: common
version: 1.0.0
repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami
完成后拉取依赖:
helm dep update
然后安装Mastodon:
helm -n mastodon install mastodon ./ -f values.yaml
此时安装完成,但还有全文检索功能没有安装。如果把之前安装PostgreSQL和Redis的方法来对ElasticSearch使用的话,会发现仍然遇到架构问题。因为Bitnami会使用一个init容器来修改内核参数,这个init容器同样不支持ARM。而如果把这个容器替换的话,则会出现莫名其妙的资源占用过高,很容易导致系统瘫痪。所以这里推荐使用亚马逊Fork的版本OpenSearch,首先克隆存储库下来:
git clone https://github.com/opensearch-project/helm-charts.git
进入其中的charts/opensearch
目录,修改values.yaml文件来禁用TLS,在61和62行之间,也就是security:
下面添加disabled: true
,以及修改297行,如果算上之前添加的一行则为298行,将securityConfig.enabled
修改为false
,然后部署:
helm -n mastodon install opensearch ./ -f values.yaml
部署完成后修改Mastodon配置,先用kubectl -n mastodon get svc
获取服务名,然后使用kubectl -n mastodon edit cm mastodon-env
打开ConfigMap进行配置,在data
中添加:
ES_ENABLE: "true"
ES_HOST: opensearch-cluster-master.mastodon.svc.cluster.local
ES_PORT: "9200"
其中ES_HOST中的域名规则是:服务名.命名空间.svc.集群域名,默认情况下应该是以上示例中的内容,如果有其他变化应按需修改。保存后重启Mastodon:
kubectl -n mastodon rollout restart deployment -n mastodon mastodon-web
现在使用kubectl -n mastodon exec -it deployment/mastodon-web -- bash
进入mastodon容器中建立索引:
bin/tootctl search deploy
进度条走完后索引建立完成,现在就部署完毕了,按照上一章结尾配置管理员密码即可
更新版本
执行前最好进行数据库备份。
和部署时相同,进入Chart目录中,然后执行以下命令拉去最新的镜像并更新:
helm -n mastodon upgrade mastodon ./ --reuse-values --set image.repository="ghcr.io/mastodon/mastodon" --set image.tag="latest"
其中--reuse-values
是为了保留已经使用的values配置。
如果更新出现错误,可以使用Helm进行回滚,首先执行helm -n mastodon history mastodon
来查看可用的旧版本。由于之前的更新方法仅更新了镜像,所以历史记录中的版本号还会显示旧的版本号,不过可以通过记录的更新时间来判断。
执行下列命令回滚:
helm -n mastodon rollback mastodon 历史版本序号
这里的序号为查看版本时最前方显示的数字编号,而不是后面的Chart或App的版本号。
可能出现的错误
无法发送注册邮件
首先检查是不是在垃圾邮件箱中,然后查看发件代理的后台是否有发送记录,如果有说明被接收方拦下,这个只能找发件代理解决。如果后台没有记录,则先通过telnet测试能否发送,如果发送成功,则说明问题出在mastodon中,如果检查配置没有错误的话,可能是作业调度程序sidekiq出现故障导致没有进行发件作业,可以使用以下命令重启:
kubectl rollout restart deployment -n mastodon mastodon-sidekiq-all-queues
无法建立索引,提示“You can't set the item's total value to less than the current progress”
似乎是进度条的问题,在Mastodon主容器内执行以下命令即可:
sed -E 's/indices.sum.+/2000/g' -i lib/mastodon/search_cli.rb
参考文章
Create your own “Twitter” in 10 minutes
Install Mastodon in Kubernetes
MastodonのメールサーバにSendGridを使う際のポイント
Getting Mastodon working with Amazon S3 file-hosting
How can I replace the Image used in Helm Chart to make it support ARM architecture?
Comments NOTHING