使用1Panel部署Mastodon并配置中文搜索

前言

部署 Mastodon 已经不是稀奇的事情了，但是我还是想分享一下我的部署方式，可能相对来说更适合小白。本篇教程非 1Panel 同样适用。

关于部署 Mastodon，本攻略搭建的并非原版 Mastodon，而是基于 Glitch 的 Fork——Chuckya，相比于原版有更多的可配置项目，也基本上无需修改源代码了。

为什么用 1Panel

可能就像当初大家用宝塔一样，我用的是 1panel，因为他可视化的文件管理，自带 SSH，配置证书非常方便，有便捷的备份设置，很适合小白使用。

用了 1Panel 自然要用 Docker 部署，这也是最便捷的方式之一。

准备工作

挑选服务器，如果你要搭建 Mastodon，推荐最少 2C4G 的服务器，4C8G 会更好。请不要使用国内的服务器！

挑选域名

安装 1Panel。（不必再特意安装 Docker，安装 1Panel 时已一起安装完。）

正式安装

选择一个文件存放你的 Mastodon

我放在了 /opt/Mastodon

使用 1Panel 你可以在这里进行创建文件夹操作，或进入终端输入：

Copy
mkdir /opt/mastodon

从仓库拉取 Mastodon 的配置文件，并修改

仓库地址 （Chuckya Fork）
https://github.com/TheEssem/mastodon

我们需要拉取两个文件：docker-compose.yml 与 .env.production.sample
使用 1Panel 你可以下载后再上传，或进入终端输入：

Copy
cd Mastodon
wget https://gcore.jsdelivr.net/gh/TheEssem/mastodon@refs/heads/main/docker-compose.yml
wget https://gcore.jsdelivr.net/gh/TheEssem/mastodon@refs/heads/main/.env.production.sample
cp ./.env.production.sample .env.production

修改 docker-compose.yml

如果你想使用 Glitch 分支或者原版，只需要修改 image 即可。

我将 db、redis 部分都注释掉了，为了清楚展示，我在下方代码中将这两部分全部删除了。Elasticsearch 使用 1Panel 安装反而变麻烦了，所以直接一起安装。

需要修改的部分： 将 network 全部替换为 1panel-network，并在最后添加 external 属性。

（格式可能存在错误，请直接拉取仓库中的文件进行修改）

Copy
services:
web:
image: ghcr.io/theessem/mastodon:nightly #根据自己需求更改
restart: always
env_file: .env.production
command: bundle exec puma -C config/puma.rb
networks: #需要修改
- 1panel-network
healthcheck:
# prettier-ignore
test: ['CMD-SHELL',"curl -s --noproxy localhost localhost:3000/health | grep -q 'OK' || exit 1"]
ports:
- '127.0.0.1:3000:3000' #根据自己需求更改
volumes:
- ./public/system:/mastodon/public/system
es:
restart: always
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.4
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
- "xpack.license.self_generated.type=basic"
- "xpack.security.enabled=false"
- "xpack.watcher.enabled=false"
- "xpack.graph.enabled=false"
- "xpack.ml.enabled=false"
- "bootstrap.memory_lock=true"
- "cluster.name=es-mastodon"
- "discovery.type=single-node"
- "thread_pool.write.queue_size=1000"
networks:
- 1panel-network
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
volumes:
- ./elasticsearch:/usr/share/elasticsearch/data
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
ports:
- '127.0.0.1:9200:9200'

streaming:
image: ghcr.io/theessem/mastodon-streaming:nightly #根据自己需求更改
restart: always
env_file: .env.production
command: node ./streaming/index.js
networks: #需要修改
- 1panel-network
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', "curl -s --noproxy localhost localhost:4000/api/v1/streaming/health | grep -q 'OK' || exit 1"]
ports:
- '127.0.0.1:4000:4000' #根据自己需求更改

sidekiq:
image: ghcr.io/theessem/mastodon:nightly #根据自己需求更改
restart: always
env_file: .env.production
command: bundle exec sidekiq
networks: #需要修改
- 1panel-network
volumes:
- ./public/system:/mastodon/public/system
healthcheck:
test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]

#需要修改的：
networks:
1panel-network:
external: true

目前，默认将 Mastodon 的 web 服务设置在 3000 端口，streaming 为 4000 端口。

从 1Panel 应用商店安装 PostgreSQL、Redis

一键安装即可，PostgreSQL 的版本可以自行进行选择。

创建数据库

在安装完成后，从左侧导航栏进入 数据库。

并选择 PostgreSQL。

点击创建数据库，自定义你的数据库名称、用户名、密码。

查看你的 PostgreSQL 和 Redis 连接信息：

PostgreSQL：

点击进入，此处会有一个容器连接地址：

Redis：同理

额外需要用到此处的密码

执行安装

Copy
cd /opt/Mastodon
docker-compose run --rm web bundle exec rake mastodon:setup

Copy
Domain name: 你的域名

Single user mode disables registrations and redirects the landing page to your public profile.

Do you want to enable single user mode? N

Are you using Docker to run Mastodon? Y

PostgreSQL host: #刚刚的容器连接地址

PostgreSQL port: 5432

Name of PostgreSQL database: mastodon

Name of PostgreSQL user: mastodon

Password of PostgreSQL user: （这里写上面你给mastodon设置的数据库密码）

Database configuration works! 🎆

Redis host: #刚刚的容器连接地址

Redis port: 6379

Redis password: #刚刚的密码

Redis configuration works! 🎆

Do you want to store uploaded files on the cloud? N #根据自己需求，我是放在本地了

Do you want to send e-mails from localhost? N #设置你的SMTP服务器

SMTP server:

SMTP port: 587

SMTP username:

SMTP password:

SMTP authentication: plain

SMTP OpenSSL verify mode: none

E-mail address to send e-mails “from”:

Send a test e-mail with this configuration right now? Y

This configuration will be written to .env.production

Save configuration? Yes

在运行后会生成串配置信息，你需要将其填写到你的 .env.production 中。

继续生成管理员账户

截至目前版本，生成管理员账户已经没有 BUG。

.env.production 的可修改内容

我用 AI 进行了翻译，可以进行参考，Glitch 版本可以对 Mastodon 进行更多的自定义（如字符数、最大标签数、pin 数等，Chuckya 可以设置允许上传和显示的最大附件数）

Copy
# 这是一个示例配置文件。你可以使用交互式设置向导`bundle exec rails mastodon:setup`生成你的配置，但如果你想进一步自定义设置，可能需要手动编辑。这个示例并没有展示所有可用的配置选项。请查看 https://docs.joinmastodon.org/admin/config/ 获取完整文档。

# 注意，这个文件接受的语法根据是否使用`docker-compose`略有不同。特别是，如果你使用`docker-compose`，声明的每个变量的值将被直接采用，包括引号。
# 参考：https://github.com/mastodon/mastodon/issues/16895

# 联邦设置
# ----------
# 这个标识你的服务器，且不能在之后安全地更改
# ----------
LOCAL_DOMAIN=example.com

# 如果你需要在不同于联邦使用的域名上运行Mastodon，才使用这个选项。
# 你可以阅读更多关于这个选项的内容：https://docs.joinmastodon.org/admin/config/#web-domain
# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING.
# WEB_DOMAIN=mastodon.example.com

# 如果你想有多个别名handler@example1.com
# handler@example2.com等，用于同一个用户。LOCAL_DOMAIN不应包含在内。用逗号分隔
# ALTERNATE_DOMAINS=example1.com,example2.com

# 用于出站请求的HTTP代理（可选）
# http_proxy=http://gateway.local:8118
# 隐藏服务的访问控制。
# ALLOW_ACCESS_TO_HIDDEN_SERVICE=true

# 授权抓取模式（可选）
# 需要远程服务器在抓取推文时进行身份验证，详见
# https://docs.joinmastodon.org/admin/config/#authorized_fetch
# AUTHORIZED_FETCH=true

# 受限联邦模式（可选）
# 仅允许与特定域进行联邦，详见
# https://docs.joinmastodon.org/admin/config/#whitelist_mode
# LIMITED_FEDERATION_MODE=true

# Redis
# -----
REDIS_HOST=localhost
REDIS_PORT=6379

# PostgreSQL
# ----------
DB_HOST=/var/run/postgresql
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=
DB_PORT=5432

# Elasticsearch (可选)
# ------------------------
#ES_ENABLED=true
#ES_HOST=localhost
#ES_PORT=9200
# Elasticsearch身份验证（可选）
#ES_USER=elastic
#ES_PASS=password

# 秘密
# -------
# 使用`RAILS_ENV=production bundle exec rails secret`任务生成每个密钥（如果使用docker compose，则使用`docker-compose run --rm web bundle exec rails secret`）
# -------
SECRET_KEY_BASE=
OTP_SECRET=

# 加密密钥
# ------------------
# 必须在所有服务器进程中可用且值相同
# 这些是私有/秘密值，不要在托管环境外分享
# 使用`bin/rails db:encryption:init`生成新的密钥
# 不要更改这些密钥，否则会导致数据丢失和其他问题
# ------------------
# ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=
# ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=
# ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=

# Web Push
# --------
# 使用`bundle exec rails mastodon:webpush:generate_vapid_key`生成（第一个是私钥，第二个是公钥）
# 你应该只为实例生成一次。如果你后来决定更改它，所有推送订阅将
# 会被无效，需要用户再次访问网站以重新订阅。
# --------
VAPID_PRIVATE_KEY=
VAPID_PUBLIC_KEY=

# 注册
# -------------

# 单用户模式将禁用注册，并将首页重定向到第一个用户资料
# SINGLE_USER_MODE=true

# 防止使用以下邮箱域名进行注册
# EMAIL_DOMAIN_DENYLIST=example1.com|example2.de|etc

# 仅允许使用以下邮箱域名进行注册
# EMAIL_DOMAIN_ALLOWLIST=example1.com|example2.de|etc

#TODO 移动这个
# 可选地更改默认语言
# DEFAULT_LOCALE=de

# 发送邮件
# ------------
SMTP_SERVER=
SMTP_PORT=587
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=notifications@example.com

# 文件存储（可选）
# -----------------------
# 附件主机必须允许来自WEB_DOMAIN或
# 如果未设置WEB_DOMAIN，则来自LOCAL_DOMAIN的跨域请求。例如，服务器可能具有以下标头字段：
# Access-Control-Allow-Origin: https://192.168.1.123:9000/
# -----------------------
#S3_ENABLED=true
#S3_BUCKET=files.example.com
#AWS_ACCESS_KEY_ID=
#AWS_SECRET_ACCESS_KEY=
#S3_ALIAS_HOST=files.example.com

# Swift（可选）
# 附件主机必须允许跨域请求 - 请参阅上述描述。
# SWIFT_ENABLED=true
# SWIFT_USERNAME=
# 对于 Keystone V3，SWIFT_TENANT 的值应为项目名称
# SWIFT_TENANT=
# SWIFT_PASSWORD=
# 某些 OpenStack V3 提供商在高负载期间可能需要设置PROJECT_ID（可选）
# SWIFT_PROJECT_ID=
# 支持 Keystone V2 和 V3 URL。建议使用 V3 URL 以避免令牌速率限制问题。
# SWIFT_AUTH_URL=
# SWIFT_CONTAINER=
# SWIFT_OBJECT_URL=
# SWIFT_REGION=
# 默认为 'default'
# SWIFT_DOMAIN_NAME=
# 默认为 60 秒。设置为 0 以禁用
# SWIFT_CACHE_TTL=

# 可选的多服务器设置中的资产主机
# 资产主机必须允许来自WEB_DOMAIN或LOCAL_DOMAIN的跨域请求
# 例如，服务器可能具有以下标头字段：
# Access-Control-Allow-Origin: https://example.com/
# CDN_HOST=https://assets.example.com

# 可选的允许为你的实例服务媒体的主机列表
# 如果你在自定义CSS或about页面中包含外部媒体，
# 或者你的数据存储提供商使用重定向到其他域时，这很有用。
# EXTRA_DATA_HOSTS=https://data.example1.com|https://data.example2.com

# S3的可选别名（例如，使用自定义域名提供文件，可能使用Cloudfront或Cloudflare）
# S3_ALIAS_HOST=

# 流式API集成
# STREAMING_API_BASE_URL=

# 外部身份验证（可选）
# ----------------------------------
# LDAP身份验证（可选）
# LDAP_ENABLED=true
# LDAP_HOST=localhost
# LDAP_PORT=389
# LDAP_METHOD=simple_tls
# LDAP_BASE=
# LDAP_BIND_DN=
# LDAP_PASSWORD=
# LDAP_UID=cn
# LDAP_MAIL=mail
# LDAP_SEARCH_FILTER=(|(%{uid}=%{email})(%{mail}=%{email}))
# LDAP_UID_CONVERSION_ENABLED=true
# LDAP_UID_CONVERSION_SEARCH=., -
# LDAP_UID_CONVERSION_REPLACE=_

# PAM身份验证（可选）
# PAM身份验证使用“email”PAM变量生成邮箱，
# 并可选地使用PAM_DEFAULT_SUFFIX作为fallback
# “email” pam环境变量由以下提供：
# https://github.com/devkral/pam_email_extractor
# PAM_ENABLED=true
# 用于邮箱地址生成的邮箱域名fallback（默认为LOCAL_DOMAIN）
# PAM_EMAIL_DOMAIN=example.com
# PAM服务的名称（评估pam的“auth”部分）
# PAM_DEFAULT_SERVICE=rpam
# 用于检查用户是否可以注册的PAM服务名称（默认为nil（禁用））
# PAM_CONTROLLED_SERVICE=rpam

# 全局OAuth设置（可选）：
# 如果你只有一个策略，可能希望启用这个
# OAUTH_REDIRECT_AT_SIGN_IN=true

# 可选CAS身份验证（参考omniauth-cas）：
# CAS_ENABLED=true
# CAS_URL=https://sso.myserver.com/
# CAS_HOST=sso.myserver.com/
# CAS_PORT=443
# CAS_SSL=true
# CAS_VALIDATE_URL=
# CAS_CALLBACK_URL=
# CAS_LOGOUT_URL=
# CAS_LOGIN_URL=
# CAS_UID_FIELD='user'
# CAS_CA_PATH=
# CAS_DISABLE_SSL_VERIFICATION=false
# CAS_UID_KEY='user'
# CAS_NAME_KEY='name'
# CAS_EMAIL_KEY='email'
# CAS_NICKNAME_KEY='nickname'
# CAS_FIRST_NAME_KEY='firstname'
# CAS_LAST_NAME_KEY='lastname'
# CAS_LOCATION_KEY='location'
# CAS_IMAGE_KEY='image'
# CAS_PHONE_KEY='phone'

# 可选SAML身份验证（参考omniauth-saml）
# SAML_ENABLED=true
# SAML_ACS_URL=http://localhost:3000/auth/auth/saml/callback
# SAML_ISSUER=https://example.com
# SAML_IDP_SSO_TARGET_URL=https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO
# SAML_IDP_CERT=
# SAML_IDP_CERT_FINGERPRINT=
# SAML_NAME_IDENTIFIER_FORMAT=
# SAML_CERT=
# SAML_PRIVATE_KEY=
# SAML_SECURITY_WANT_ASSERTION_SIGNED=true
# SAML_SECURITY_WANT_ASSERTION_ENCRYPTED=true
# SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED=true
# SAML_ATTRIBUTES_STATEMENTS_UID="urn:oid:0.9.2342.19200300.100.1.1"
# SAML_ATTRIBUTES_STATEMENTS_EMAIL="urn:oid:1.3.6.1.4.1.5923.1.1.1.6"
# SAML_ATTRIBUTES_STATEMENTS_FULL_NAME="urn:oid:2.16.840.1.113730.3.1.241"
# SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME="urn:oid:2.5.4.42"
# SAML_ATTRIBUTES_STATEMENTS_LAST_NAME="urn:oid:2.5.4.4"
# SAML_UID_ATTRIBUTE="urn:oid:0.9.2342.19200300.100.1.1"
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED=
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL=

# 自定义设置
# ---------------
# 以多种方式自定义Mastodon的行为
# ---------------

# 最大允许字符数
MAX_TOOT_CHARS=500

# 在订阅列中允许的最大主题标签数
# 请注意，将此值设置得更高可能会导致显著的
# 数据库负载
MAX_FEED_HASHTAGS=4

# 最大可钉住的帖子数
MAX_PINNED_TOOTS=5

# 最大允许的个人简介字符数
MAX_BIO_CHARS=500

# 最大个人资料字段数
MAX_PROFILE_FIELDS=4

# 最大允许的显示名称字符数
MAX_DISPLAY_NAME_CHARS=30

# 最大允许的投票选项数
MAX_POLL_OPTIONS=5

# 最大允许的投票选项字符数
MAX_POLL_OPTION_CHARS=100

# 每个推文和用户的最大表情反应数（最小为1）
MAX_REACTIONS=1

# 允许上传和显示的最大附件数
# MAX_MEDIA_ATTACHMENTS=4
# MAX_REMOTE_MEDIA_ATTACHMENTS=16

# 最大图像和视频/音频上传大小
# 单位为字节
# 1048576字节等于1兆字节
# MAX_IMAGE_SIZE=8388608
# MAX_VIDEO_SIZE=41943040

# 最大搜索结果数
# 仅在安装了Elasticsearch时相关
# MAX_SEARCH_RESULTS=20

# 最大主题标签数
# 自定义在'Explore'中显示的主题标签数
# MAX_TRENDING_TAGS=10

# 自定义表情文件的最大大小
# 如果未定义或小于MAX_EMOJI_SIZE，则使用
# MAX_EMOJI_SIZE的值作为MAX_REMOTE_EMOJI_SIZE
# 单位为字节
# MAX_EMOJI_SIZE=262144
# MAX_REMOTE_EMOJI_SIZE=262144

# 可选的hCaptcha支持
# HCAPTCHA_SECRET_KEY=
# HCAPTCHA_SITE_KEY=

# IP和会话保留
# -----------------------
# 确保修改config/sidekiq.yml中的ip_cleanup_scheduler调度
# 如果将IP_RETENTION_PERIOD设置为小于两天（172800），则调度应小于每日。
# -----------------------
IP_RETENTION_PERIOD=31556952
SESSION_RETENTION_PERIOD=31556952

将之前生成的信息填入，并做一些自定义的修改。

为 Elasticsearch 安装插件，优化中文搜索

从左侧导航栏的容器进入

选择容器名称包含 Elasticsearch 的，在操作一栏选择终端进入并连接：

打开 https://release.infinilabs.com/ ，并进入，我们需要安装 analysis-ik 与 analysis-stconvert，选择你要安装的版本。回到终端中，输入下列代码（以上方 docker-compose.yml 文件中的 7.17.4 版本为例）：

Copy
yes | elasticsearch-plugin install https://release.infinilabs.com/analysis-ik/stable/elasticsearch-analysis-ik-7.17.14.zip
elasticsearch-plugin install https://release.infinilabs.com/analysis-stconvert/stable/elasticsearch-analysis-stconvert-7.17.4.zip

完成后重启 Elasticsearch，并将你的 Elasticsearch 连接信息填入 .env.production。

之后你需要在 Mastodon 文件夹为 elasticsearch 文件夹赋权。

Copy
chown 1000:1000 -R elasticsearch

启动

Copy
docker-compose up -d

在启动后，你需要为 public 文件夹赋权，否则服务会持续报错：

Copy
chown 991:991 -R ./public

至此你的服务已经成功运行了。

设置 DNS 账户、Acme 账户并申请证书

我使用的是 Cloudflare，如果你和我一样，可以继续看下去：

获取 API Token ，创建令牌 - 使用模板（编辑 DNS），区域选择所有区域：

在 1Panel 中选择网站，根据要求安装 OpenResty，完成后进入证书 - DNS 账户

创建 DNS 账户，选择 Cloudflare，输入你的 cloudflare 账户邮箱和 Token：

创建 Acme 账户，输入邮箱（此处邮箱可随意选择）：

点击申请证书，填入你需要申请证书的网址。

创建网站

从左侧导航栏进入网站 - 网站，点击创建网站 - 反向代理，代理地址填写你的 web 地址，默认为 127.0.0.1:3000。

点击网站名或从右侧操作进入配置，点击 HTTPs，选择启用，并选择你刚刚申请的证书。

在 Cloudflare 中添加解析，将你的网站名称，指向你的服务器 IP。

此时你已经可以访问你的服务器了。

配置 Nginx

在成功运行完服务以后，我们还需要配置 Nginx，可以拉取 Mastodon 官方的 Nginx 配置文件进行查看：

Copy
wget https://gcore.jsdelivr.net/gh/TheEssem/mastodon@refs/heads/main/dist/nginx.conf

Copy
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream backend {
server 127.0.0.1:3000 fail_timeout=0;
}

upstream streaming {
# Instruct nginx to send connections to the server with the least number of connections
# to ensure load is distributed evenly.
least_conn;

server 127.0.0.1:4000 fail_timeout=0;
# Uncomment these lines for load-balancing multiple instances of streaming for scaling,
# this assumes your running the streaming server on ports 4000, 4001, and 4002:
# server 127.0.0.1:4001 fail_timeout=0;
# server 127.0.0.1:4002 fail_timeout=0;
}

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;

server {
listen 80;
listen [::]:80;
server_name example.com;
root /home/mastodon/live/public;
location /.well-known/acme-challenge/ { allow all; }
location / { return 301 https://$host$request_uri; }
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

ssl_protocols TLSv1.2 TLSv1.3;

# You can use https://ssl-config.mozilla.org/ to generate your cipher set.
# We recommend their "Intermediate" level.
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:DHE-RSA-CHACHA20-POLY1305;

ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

# Uncomment these lines once you acquire a certificate:
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

keepalive_timeout 70;
sendfile on;
client_max_body_size 99m;

root /home/mastodon/live/public;

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
gzip_static on;

location / {
try_files $uri @proxy;
}

# If Docker is used for deployment and Rails serves static files,
# then needed must replace line `try_files $uri =404;` with `try_files $uri @proxy;`.
location = /sw.js {
add_header Cache-Control "public, max-age=604800, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/assets/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/avatars/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/emoji/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/headers/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/packs/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/shortcuts/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/sounds/ {
add_header Cache-Control "public, max-age=2419200, must-revalidate";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
try_files $uri =404;
}

location ~ ^/system/ {
add_header Cache-Control "public, max-age=2419200, immutable";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
try_files $uri =404;
}

location ^~ /api/v1/streaming {
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 $scheme;
proxy_set_header Proxy "";

proxy_pass http://streaming;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";

tcp_nodelay on;
}

location @proxy {
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 $scheme;
proxy_set_header Proxy "";
proxy_pass_header Server;

proxy_pass http://backend;
proxy_buffering on;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

proxy_cache CACHE;
proxy_cache_valid 200 7d;
proxy_cache_valid 410 24h;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cached $upstream_cache_status;

tcp_nodelay on;
}

error_page 404 500 501 502 503 504 /500.html;
}

添加到你的 OpenResty 中即可。

总结

本篇是一个面向基本无代码基础，更想看图形化界面的友友提供的一种思路，在之后会更加完善一些，并更新使用 1Panel 进行文件备份的教程，第一次更新就先到这里啦。