Synapse/Element v1.163.0 Admin API 与 CLI 工具详解
逐条实测 Synapse v1.163.0 全部内置 CLI 工具与 Admin API:注册、密码哈希、签名密钥、配置生成、数据库迁移工具参数详解,用户、房间、注册令牌、共享密钥注册接口全流程闭环与错误码排障实录。
Synapse/Element v1.163.0 Admin API 与 CLI 工具详解
目标:逐条实测 Synapse v1.163.0 发行包内置的全部 CLI 管理工具与 Admin API——开户、密码哈希、签名密钥、配置生成、数据库迁移工具的参数与真实回显,加上用户、房间、注册令牌、共享密钥注册接口的完整调用闭环与错误码排障实录。已在 Ubuntu 22.04 + Synapse v1.163.0(Docker Compose 部署形态,部署过程见 《Synapse/Element v1.163.0 Docker Compose 部署指南》)实测通过,全部命令与回显均为真实执行结果。
一、环境信息
| 项目 | 值 | 说明 |
|---|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS(x86_64) | 服务器环境 |
| Synapse | v1.163.0(2026-10-14 发布) | matrixdotorg/synapse 官方发行包 |
| Element Web | v1.12.32(2026-10-16 发布) | 同系列部署,本文不直接操作 |
| server_name | matrix.local | 用户标识域名部分(@admin:matrix.local) |
| 主配置文件 | /opt/synapse/data/homeserver.yaml | CLI 工具以 -c 读取它 |
| CLI 调用形态 | docker compose exec synapse <工具名> | 工作目录 /opt/synapse,见 1.1 说明 |
| Admin API 基址 | http://localhost:8141 | 端口映射见部署篇 |
| 演示账号 | admin(管理员)/ alice / bob / carol,密码 q1w2e3r4 | admin 由部署篇 4.7 以 -a 注册 |
1.1 CLI 工具的调用形态
Synapse 官方 Docker 发行包把全部 CLI 管理工具内置在发行包内,本文统一用 docker compose exec synapse <工具名> 调用(工作目录 /opt/synapse,与部署篇一致):
docker compose exec synapse register_new_matrix_user --help
usage: register_new_matrix_user [-h] [-u USER] [--exists-ok] [-p PASSWORD |
--password-file PASSWORD_FILE] [-t USER_TYPE]
[-a | --no-admin] (-c CONFIG |
-k SHARED_SECRET)
[server_url]
💡 说明:如果是包管理器(Debian/Ubuntu 官方 apt 源)或 pip 安装的服务器,这些工具直接在系统 PATH 中(如直接执行
register_new_matrix_user),去掉docker compose exec synapse前缀、配置路径换成-c /etc/matrix-synapse/homeserver.yaml即可,参数完全一致。本文所有 CLI 命令的参数部分两种形态通用。
二、工具概览
Synapse 的管理能力分布在两条通道上:CLI 工具(服务器本机管理面,直接读配置文件与密钥,不需要网络令牌)与 Admin API(HTTP 管理 API,走 access_token 认证,远程可调、适合脚本化批量操作)。本章先建立全景,后续章节逐个实测。
2.1 两条管理通道的分工
| 通道 | 定位 | 认证凭据 | 典型场景 |
|---|---|---|---|
| CLI 工具(本文四章、五章) | 服务器本机管理面 | 读配置文件 / 直传共享密钥 | 初始化开户、生成密钥与配置、数据库迁移、注册审计 |
Admin API(/_synapse/admin/,本文六~十章) | HTTP 管理 API | 管理员 access_token | 远程批量用户/房间治理、自动化运维脚本 |
Client-Server API(/_matrix/) | 终端用户日常 API | 用户 access_token | 收发消息、同步、建房(部署篇 4.10 全链路实测) |
关键差异:CLI 工具多数是「一次性任务」形态(生成、迁移、审计),Admin API 则是「持续治理」形态(增删改查均可编程)。同一件事常有两条路径——比如开户既能用 CLI 的 register_new_matrix_user(4.1),也能用 Admin API 的共享密钥注册接口(第八章),选型对比见 8.4。
💡 技术拓展:Admin API 的版本前缀 v1 与 v2 并存。Synapse Admin API 中用户管理(
/users端点)已演进到 v2(返回字段更全、支持 PUT 修改用户资料),而 whois、rooms、reset_password、deactivate 等仍为 v1。这是官方渐进式演进的结果:新功能落在 v2,旧端点保持 v1 兼容。同一脚本里按端点分别取对应版本即可,本文所有端点均按官方现状逐条标注实测。
2.2 Synapse v1.163.0 内置 CLI 工具家族
发行包共内置 10 个管理工具,全部在本文实测(--help 或完整运行):
| 工具 | 用途 | 类别 | 实测位置 |
|---|---|---|---|
register_new_matrix_user | 注册新用户(可指定管理员) | 账号 | 4.1 |
hash_password | 生成密码哈希 | 账号 | 4.2 |
generate_signing_key | 生成服务器签名密钥文件 | 密钥 | 4.3 |
export_signing_key | 导出签名密钥公钥部分 | 密钥 | 4.3 |
generate_config | 生成 homeserver.yaml 主配置 | 配置 | 5.1 |
generate_log_config | 生成日志配置文件 | 配置 | 5.2 |
synapse_review_recent_signups | 新注册用户审计报告 | 审计 | 5.3 |
synapse_port_db | SQLite → PostgreSQL 数据迁移 | 数据库 | 5.4 |
update_synapse_database | 数据库 schema 升级 | 数据库 | 5.5 |
synctl | 服务进程启停(非 Docker 部署形态) | 进程 | 5.6 |
2.3 本文实测的 Admin API 端点总览
| 方法 | 端点 | 用途 | 实测位置 |
|---|---|---|---|
| GET | /_synapse/admin/v1/server_version | 查询服务器版本(无需认证) | 6.2 |
| GET | /_synapse/admin/v2/users | 用户列表(分页/过滤) | 7.1 |
| GET/PUT | /_synapse/admin/v2/users/{user_id} | 单用户详情 / 修改资料 | 7.2 |
| GET | /_synapse/admin/v1/whois/{user_id} | 查询用户会话与连接记录 | 7.3 |
| GET/PUT | /_synapse/admin/v1/users/{user_id}/admin | 管理员标志查询 / 提降权 | 7.4 |
| POST | /_synapse/admin/v1/reset_password/{user_id} | 重置用户密码 | 7.5 |
| POST | /_synapse/admin/v1/deactivate/{user_id} | 注销用户 | 7.6 |
| GET/POST | /_synapse/admin/v1/register | 共享密钥注册接口(nonce + HMAC) | 第八章 |
| GET | /_synapse/admin/v1/rooms | 房间列表 | 9.1 |
| DELETE | /_synapse/admin/v1/rooms/{room_id} | 删除房间 | 9.2 |
| GET/POST/DELETE | /_synapse/admin/v1/registration_tokens、/new、/{token} | 注册令牌管理 | 9.3 |
| GET | /_synapse/admin/v1/statistics/users/media | 用户媒体占用统计 | 9.4 |
三、前置条件
3.1 管理员账号
Admin API 只对 admin: true 的账号开放。本文环境的 admin 账号在部署篇 4.7 用 CLI 注册时以 -a 声明了管理员身份,验证方法是查用户列表中的 admin 字段(第七章 7.1 的实测回显里 "admin":true)。如果还没有管理员账号,先按部署篇 4.7 或本文 4.1 的 -a 参数注册一个。
3.2 获取 access_token
Admin API 用管理员账号的 access_token 认证。token 通过登录接口获取:
curl -s -X POST http://localhost:8141/_matrix/client/v3/login \
-H 'Content-Type: application/json' \
-d '{"type":"m.login.password","identifier":{"type":"m.id.user","user":"admin"},"password":"q1w2e3r4"}'
{"user_id":"@admin:matrix.local","access_token":"syt_YWRtaW4_eOAVGhKswzjXUYoDyLMk_1Dc265","home_server":"matrix.local","device_id":"OSXBGPFLSU"}
从回显复制 access_token 值赋给变量 AT,后文所有 Admin API 命令统一引用它:
# token 长期有效;每次重新登录会生成新 token,旧 token 不失效(多设备多会话)
AT='syt_YWRtaW4_eOAVGhKswzjXUYoDyLMk_1Dc265'
⚠️ 注意:access_token 等同账号本身,泄露即等于账号被盗。本文回显中的 token 是演示环境一次性会话凭据,生产环境不要把 token 写进脚本仓库或日志。
3.3 确认 registration_shared_secret 已配置
CLI 注册工具(-c/-k 两种方式)与共享密钥注册接口(第八章)都依赖主配置中的注册共享密钥。确认方法:
grep 'registration_shared_secret' /opt/synapse/data/homeserver.yaml
registration_shared_secret: "US&am;b2mR3dCi1YrHv1D4AeU01H.Yd,wuIujYL+1,,vH:KG~X"
该值在部署篇 4.3 执行 generate_config 时随机生成(参数逐项解释见 《Synapse/Element v1.163.0 配置参数详解》第四章)。它等同「半个管理员」:持有者可以任意开户,生产环境必须妥善保管。
四、账号与密钥类 CLI 工具
4.1 register_new_matrix_user:注册新用户
这是 Synapse 最常用的管理工具:在注册开关关闭的情况下也能开户(走共享密钥通道),并可指定是否管理员。先看完整帮助:
docker compose exec synapse register_new_matrix_user --help
usage: register_new_matrix_user [-h] [-u USER] [--exists-ok] [-p PASSWORD |
--password-file PASSWORD_FILE] [-t USER_TYPE]
[-a | --no-admin] (-c CONFIG |
-k SHARED_SECRET)
[server_url]
Used to register new users with a given homeserver when registration has been
disabled. The homeserver must be configured with the
'registration_shared_secret' option set.
positional arguments:
server_url URL to use to talk to the homeserver. By default,
tries to find a suitable URL from the configuration
file. Otherwise, defaults to 'http://localhost:8008'.
options:
-h, --help show this help message and exit
-u, --user USER Local part of the new user. Will prompt if omitted.
--exists-ok Do not fail if the user already exists. The user
account will not be updated.
-p, --password PASSWORD
New password for user. Will prompt for a password if
this flag and `--password-file` are both omitted.
--password-file PASSWORD_FILE
File containing the new password for user. If set,
will override `--password`.
-t, --user_type USER_TYPE
User type as specified in
synapse.api.constants.UserTypes
-a, --admin Register new user as an admin. Will prompt if --no-
admin is not set either.
--no-admin Register new user as a regular user. Will prompt if
--admin is not set either.
-c, --config CONFIG Path to server config file. Used to read in shared
secret.
-k, --shared-secret SHARED_SECRET
Shared secret as defined in server config file.
参数要点(默认值均来自上述实测帮助):
| 参数 | 说明 |
|---|---|
-c CONFIG | 从配置文件读共享密钥(最常用) |
-k SHARED_SECRET | 直接传共享密钥字符串,不读配置文件 |
-c 与 -k 二选一 | 帮助文本中的 (-c CONFIG | -k SHARED_SECRET) 表示必选其一 |
-u USER | 用户名本地部分(省略则交互式询问) |
-p / --password-file | 密码来源,二者都省略则交互式输入;--password-file 优先 |
-a / --no-admin | 管理员 / 普通用户,二者都省略则交互式询问 |
--exists-ok | 用户已存在时不报错(不更新已有账号) |
-t USER_TYPE | 用户类型,取值见 synapse.api.constants.UserTypes |
server_url | 服务地址,省略时从配置推断,默认 http://localhost:8008 |
实测一:-c 方式注册普通用户 carol(读配置文件拿共享密钥):
docker compose exec synapse register_new_matrix_user \
-c /data/homeserver.yaml --no-admin -u carol -p q1w2e3r4 http://localhost:8008
Sending registration request...
Success!
实测二:-k 方式注册普通用户 d1k01(直接传共享密钥字符串,不读配置文件):
docker compose exec synapse register_new_matrix_user \
-k 'US&am;b2mR3dCi1YrHv1D4AeU01H.Yd,wuIujYL+1,,vH:KG~X' \
--no-admin -u d1k01 -p q1w2e3r4 http://localhost:8008
Sending registration request...
Success!
注册结果用 Admin API 用户列表复核(完整回显见 7.1),输出节选(实测,仅取 carol 段),用户 @carol:matrix.local 与 @d1k01:matrix.local 均已出现:
{"users":[{...,"name":"@carol:matrix.local",...,"displayname":"carol",...}],"total":5}
💡 技术拓展:
-c与-k的选型。两种方式最终都把共享密钥交给注册工具计算签名,差别只在密钥来源——-c由工具自己读配置文件,适合在服务器本机操作;-k把密钥写进命令行,适合跨机调用(管理机上没有 homeserver.yaml,只有密钥值)。注意-k方式密钥会留在 shell 历史里,生产环境用完及时清理历史或改用--password-file类的文件通道。本文服务器本机操作,两种都实测可用。
实测三:--exists-ok 重复注册(已存在的用户不报错、也不更新):
docker compose exec synapse register_new_matrix_user \
-c /data/homeserver.yaml --no-admin -u carol -p q1w2e3r4 --exists-ok http://localhost:8008
Sending registration request...
User already exists. Skipping.
实测四:不带 --exists-ok 重复注册(应报错):
docker compose exec synapse register_new_matrix_user \
-c /data/homeserver.yaml --no-admin -u carol -p q1w2e3r4 http://localhost:8008
Sending registration request...
ERROR! Received 400 Bad Request
User ID already taken.
⚠️ 注意:已注销(deactivated)的用户同样占用 user ID,重复注册报同样的
User ID already taken.——本文环境实测:temp01~temp05、d1k01 等测试账号注销后再次注册均报 400,而默认用户列表看不到它们(验证方法见 7.6 与 FAQ Q2)。因此注销是不可逆操作,用户名不可复用。
4.2 hash_password:生成密码哈希
hash_password 按服务器当前的哈希参数计算密码哈希,用于直接写入数据库重置密码等场景;日常重置密码更推荐 Admin API 的 reset_password(7.5,一步到位)。帮助与参数:
docker compose exec synapse hash_password --help
usage: hash_password [-h] [-p PASSWORD] -c CONFIG
Calculate the hash of a new password, so that passwords can be reset
options:
-h, --help show this help message and exit
-p, --password PASSWORD
New password for user. Will prompt if omitted.
-c, --config CONFIG Path to server config file. Used to read in
bcrypt_rounds and password_pepper.
-c 是必选的:哈希结果受配置文件里 bcrypt_rounds(哈希强度)与 password_pepper(胡椒值)影响,必须与服务器配置一致,算出的哈希才能被服务器认可。
实测:生成 q1w2e3r4 的哈希:
docker compose exec synapse hash_password -c /data/homeserver.yaml -p q1w2e3r4
$2b$12$P4j/erdBSB/IBeZCBTErLubUmTkiQ0tc1QclftkcW1Qbg3QQ9v5G2
输出解读:$2b$12$ 前缀中 2b 是 bcrypt 算法版本标识、12 是 cost 因子(对应配置 bcrypt_rounds: 12 默认值);后面是盐与哈希正文。
同一密码两次运行输出不同(实测):另一次执行同命令输出为 $2b$12$GbchYBM5cAIUi3V8eRjO6.kRzw.0BFQg4FB5ESQyKb9xYj0C5OFH6——bcrypt 每次哈希都生成随机盐,这是正常现象,两个哈希都能通过服务器校验。不要用「字符串是否相同」来比对哈希,用登录验证。
💡 技术拓展:密码哈希算法不止 bcrypt 一种。常见方案对比——
算法 特点 适用场景 bcrypt 成熟、参数少(cost)、抗 GPU 弱于新一代 大量存量系统的默认选择 Argon2id 2015 密码哈希竞赛冠军,抗 GPU/内存攻击最强 新系统首选 scrypt 内存困难型,介于两者之间 需要内存硬度但无 Argon2 库时 PBKDF2 纯迭代、GPU 友好(对攻击者),胜在普及度 合规场景、旧系统 Synapse v1.163.0 实际采用 bcrypt(cost 由
bcrypt_rounds控制,参数详解见 《Synapse/Element v1.163.0 配置参数详解》第四章),对中小规模部署完全够用;调大bcrypt_rounds可增加离线破解成本,但登录 CPU 开销同步上升。
4.3 generate_signing_key 与 export_signing_key:签名密钥管理
签名密钥是服务器的身份根基:服务器用它对事件、联邦请求签名,其他服务器据此验证「消息确实来自这台服务器」。两个工具分别负责生成与导出。
generate_signing_key:生成新密钥文件:
docker compose exec synapse generate_signing_key --help
usage: generate_signing_key [-h] [-o OUTPUT_FILE]
options:
-h, --help show this help message and exit
-o, --output_file OUTPUT_FILE
Where to write the output to
实测生成一个演示密钥文件(成功无输出):
docker compose exec synapse generate_signing_key -o /data/d1-demo.key
(无输出,文件生成即成功)
export_signing_key:导出密钥的公钥部分:
docker compose exec synapse export_signing_key --help
usage: export_signing_key [-h] [-x] [--expiry-ts EXPIRY_TS]
key_file [key_file ...]
positional arguments:
key_file The key file to read
options:
-h, --help show this help message and exit
-x format the output for inclusion in the
old_signing_keys config setting
实测导出运行中服务器的既有签名密钥与刚生成的演示密钥:
docker compose exec synapse export_signing_key /data/matrix.local.signing.key
ed25519:a_vZbi cDSmEuZ4919+l9alH3LbzdN2qaeLlX4+roTsYOkpDOc
docker compose exec synapse export_signing_key /data/d1-demo.key
ed25519:a_ihxe 6kQkxcqBl157qun3k3Rnd0tkPy560X1nO4JFVcbalUc
输出解读:第一段 ed25519:a_vZbi 是密钥 ID(算法 ed25519 + 随机版本后缀),第二段是 base64 公钥。-x 参数则按 old_signing_keys 配置项的格式输出(密钥轮换时保留旧公钥用),--expiry-ts 给该格式附加过期时间戳。
实测清理演示密钥文件:
docker compose exec synapse rm /data/d1-demo.key
(无输出,删除即成功)
⚠️ 注意:运行中服务器的签名密钥(部署篇 4.3 生成的
matrix.local.signing.key)不要随意替换——联邦场景下其他服务器靠它验证历史事件来源,换新密钥等于换身份;确需轮换时走「新密钥写入old_signing_keys保留旧公钥」的官方流程。
五、配置、数据库与审计类 CLI 工具
5.1 generate_config:生成主配置
部署篇 4.2/4.3 已经用它完成了初始化(生成 homeserver.yaml 与全部密钥),这里是完整的参数手册:
docker compose exec synapse generate_config --help
usage: generate_config [-h] [--config-dir CONFIG_DIR] [--data-dir DATA_DIR]
[--server-name SERVER_NAME] [--report-stats {yes,no}]
[--generate-secrets] [-o OUTPUT_FILE]
[--header-file HEADER_FILE]
options:
-h, --help show this help message and exit
--config-dir CONFIG_DIR
The path where the config files are kept. Used to
create filenames for things like the log config and
the signing key. Default: CONFDIR
--data-dir DATA_DIR The path where the data files are kept. Used to create
filenames for things like the database and media
store. Default: DATADIR
--server-name SERVER_NAME
The server name. Used to initialise the server_name
config param, but also used in the names of some of
the config files. Default: SERVERNAME
--report-stats {yes,no}
Whether the generated config reports homeserver usage
statistics
--generate-secrets Enable generation of new secrets for things like the
macaroon_secret_key.By default, these parameters will
be left unset.
-o, --output-file OUTPUT_FILE
File to write the configuration to. Default: stdout
--header-file HEADER_FILE
File from which to read a header, which will be
printed before the generated config.
参数解读:--server-name 决定用户标识域名且影响密钥文件命名(生成后不易更改,部署前想清楚);--generate-secrets 让 registration_shared_secret、macaroon_secret_key 等密钥项随机生成(不加则留空,需手工填);-o 缺省输出到 stdout,便于先审阅再落盘;--report-stats 选择是否向 matrix.org 上报匿名使用统计(本文环境选择 no)。生成结果逐项解释见 《Synapse/Element v1.163.0 配置参数详解》。
5.2 generate_log_config:生成日志配置
docker compose exec synapse generate_log_config --help
usage: generate_log_config [-h] [-o OUTPUT_FILE] [-f LOG_FILE]
options:
-h, --help show this help message and exit
-o, --output-file OUTPUT_FILE
File to write the configuration to. Default: stdout
-f, --log-file LOG_FILE
name of the log file
参数只有两个:-o 指定输出文件(缺省 stdout),-f 指定日志文件名。部署篇 4.3 实测生成了 /opt/synapse/data/matrix.local.log.config;日志级别调整(INFO→DEBUG 排障)的操作与验证见 《Synapse/Element v1.163.0 配置参数详解》第六章。
5.3 synapse_review_recent_signups:新注册用户审计
对指定时间窗内的新注册用户生成审计报告,是治理垃圾注册的第一工具。帮助与参数:
docker compose exec synapse synapse_review_recent_signups --help
usage: synapse_review_recent_signups [-h] -c CONFIG_FILE [-s duration] [-e]
[-u] [-a]
options:
-h, --help show this help message and exit
-c, --config-path CONFIG_FILE
The config files for Synapse.
-s, --since duration Specify how far back to review user registrations for,
defaults to 7d (i.e. 7 days).
-e, --exclude-emails Exclude users that have validated email addresses.
-u, --only-users Only print user IDs that match.
-a, --exclude-app-service
Exclude appservice users.
参数要点:-s 默认回看 7 天(7d);-u 只打印命中的用户 ID(便于管道衔接后续处理);-e 排除已验证邮箱的用户(他们可信度较高);-a 排除应用服务(bot)用户。
实测一:默认 7 天窗口全量报告:
docker compose exec synapse synapse_review_recent_signups -c /data/homeserver.yaml
# Created: 2026-10-21 08:27:23
# Email: None
# IPs: ::ffff:10.89.59.1, ::ffff:10.89.59.1, ::ffff:10.89.59.1, ::ffff:10.89.59.1
# Number joined public rooms: 0
# Number joined private rooms: 1
#
@admin:matrix.local
# Created: 2026-10-21 08:27:34
# Email: None
# IPs: ::ffff:10.89.59.1, ::ffff:10.89.59.1, ::ffff:10.89.59.1
# Number joined public rooms: 0
# Number joined private rooms: 1
#
@alice:matrix.local
# Created: 2026-10-21 09:04:43
# Email: None
# IPs:
# Number joined public rooms: 0
# Number joined private rooms: 0
#
@bob:matrix.local
# Created: 2026-10-21 09:06:34
# Email: None
# IPs:
# Number joined public rooms: 0
# Number joined private rooms: 0
#
@carol:matrix.local
报告逐用户一个块:注册时间、邮箱、登录 IP 列表、加入的公开/私密房间数。本文环境 4 个用户都在 7 天窗口内全部命中;bob/carol 从未登录(IPs 为空、无房间)——这类「零行为账号」正是审计要重点盯防的。
实测二:-u -s 1d 只打印命中用户 ID:
docker compose exec synapse synapse_review_recent_signups -c /data/homeserver.yaml -u -s 1d
@admin:matrix.local
@alice:matrix.local
@bob:matrix.local
@carol:matrix.local
-u 的输出可以管道衔接 7.6 的注销接口做批量处置,或衔接 7.1 的详情查询逐个核查。
5.4 synapse_port_db:SQLite → PostgreSQL 数据迁移
Synapse 默认用 SQLite,规模上来后官方推荐迁 PostgreSQL。该工具负责搬数据:
docker compose exec synapse synapse_port_db --help
输出节选(实测首尾):
usage: synapse_port_db [-h] [-v] --sqlite-database SQLITE_DATABASE
--postgres-config POSTGRES_CONFIG [--curses]
[--batch-size BATCH_SIZE]
A script to port an existing synapse SQLite database to a new PostgreSQL
database.
options:
-h, --help show this help message and exit
-v
--sqlite-database SQLITE_DATABASE
The snapshot of the SQLite database file. This must
not be currently used by a running synapse server
--postgres-config POSTGRES_CONFIG
The database config file for the PostgreSQL database
--curses display a curses based progress UI
--batch-size BATCH_SIZE
The number of rows to select from the SQLite table
each iteration [default=1000]
参数解读:--sqlite-database 指向 SQLite 库的快照副本(帮助原文明确要求「must not be currently used by a running synapse server」——先停服、复制 homeserver.db 再迁移);--postgres-config 是一份包含 PostgreSQL 连接信息的配置文件(格式同 homeserver.yaml 的 database 段);--batch-size 每批搬运行数,默认 1000,可按机器性能调整;--curses 提供进度界面;-v 加详细日志。
完整迁移主线:停服务 → 复制 SQLite 快照 → 部署 PostgreSQL 并建库 → 执行 synapse_port_db → 把 homeserver.yaml 的 database 段改为 PostgreSQL → 启动并验证。本文环境为 SQLite 单机演示(PostgreSQL 依赖另需部署),--help 与参数为实测,全量搬运步骤以官方迁移文档为准,此处不编造搬运回显。
5.5 update_synapse_database:数据库 schema 升级
升级 Synapse 版本后,数据库 schema 变更通常在启动时自动执行;该工具用于手动触发或补跑:
docker compose exec synapse update_synapse_database --help
usage: update_synapse_database [-h] [-v] --database-config DATABASE_CONFIG
[--run-background-updates]
Updates a synapse database to the latest schema and optionally runs background
updates on it.
options:
-h, --help show this help message and exit
-v
--database-config DATABASE_CONFIG
Synapse configuration file, giving the details of the
database to be updated
--run-background-updates
run background updates after upgrading the database
schema
参数解读:--database-config 传 homeserver.yaml(工具从中读数据库连接配置);--run-background-updates 在 schema 升级完成后继续执行后台数据更新(大版本升级后建议加上,避免首批请求被后台迁移拖慢)。常规升级流程中无需手动调用——启动日志会显示 schema 版本推进过程。
5.6 synctl:服务进程启停(非 Docker 部署形态)
synctl 是裸机部署形态(pip / 包管理器安装、无 systemd 托管或 workers 多进程场景)的进程管理工具:
docker compose exec synapse synctl
usage: synctl [-h] [-w WORKERCONFIG] [-a WORKERCONFIGDIR] [--no-daemonize]
{start,stop,restart} [configfile]
synctl: error: the following arguments are required: action
(缺 action 参数的报错即其用法指纹。)参数解读:位置参数 {start,stop,restart} 三选一;configfile 传 homeserver.yaml;-w 指定单个 worker 配置、-a 指定 worker 配置目录(多进程 workers 架构用);--no-daemonize 前台运行。Docker 发行包的进程由入口程序托管(重启用 docker compose restart synapse,见 《Synapse/Element v1.163.0 配置参数详解》第二章的「三板斧」),systemd 部署则由 systemctl start matrix-synapse 托管——这两种形态都不经 synctl,它只在手工管理进程的场景出场。
六、Admin API 总览与认证
6.1 认证方式与 access_token 传递
Admin API 挂在 /_synapse/admin/ 前缀下,与终端用户 API(/_matrix/)并行;除个别公开端点(server_version)外都要求管理员账号的 access_token。token 的获取见 3.2。token 有两种传递方式,服务端等效:
| 传递方式 | 形态 | 特点 |
|---|---|---|
| URL 查询参数 | ?access_token=<token> | curl 调试直观,token 会进访问日志与 shell 历史 |
| Authorization 头 | -H "Authorization: Bearer <token>" | token 不进 URL,生产脚本更安全 |
💡 技术拓展:两种方式取舍。查询参数写法让每条命令自包含、复制即用,本文为逐条可复制采用它;部署篇 4.10 的双端互通实测用的则是
Authorization: Bearer头形态(两种在本文环境均实测可用)。生产脚本建议用请求头方式,并避免把 token 落进日志;若怀疑 token 泄露,轮换macaroon_secret_key可使全部会话失效(影响是所有人重新登录,见 《Synapse/Element v1.163.0 配置参数详解》第四章)。
6.2 首次调用:server_version
GET /_synapse/admin/v1/server_version 是唯一无需认证的 Admin 端点,适合做连通性与版本确认的第一条命令:
curl -s 'http://localhost:8141/_synapse/admin/v1/server_version'
{"server_version":"1.163.0"}
回显与实测环境版本一致,验证了 API 通道可达。运维上它也常被用作健康探针(HTTP 200 + 版本号即存活)。
6.3 分页与过滤通用约定
列表类端点共享一套分页参数,实测规律:
- 用户/房间列表:
from(起始偏移)+limit(每页条数),回显带total(用户)或total_rooms/offset(房间)字段,按total判断是否还有下一页(from递增翻页); name过滤:v2用户列表支持name=<子串>前缀匹配过滤(实测见 7.2 复核段,name=carol命中 1 条);deactivated开关:v2用户列表默认不返回已注销用户,加deactivated=true才包含(实测见 7.6)。
七、用户管理域 API
7.1 用户列表(v2)
GET /_synapse/admin/v2/users 返回全量本地用户(分页):
curl -s "http://localhost:8141/_synapse/admin/v2/users?access_token=$AT&from=0&limit=10"
输出节选(实测首尾,中间用户字段同构):
{"users":[{"name":"@admin:matrix.local","user_type":null,"is_guest":false,"admin":true,"deactivated":false,"shadow_banned":false,"displayname":"admin","avatar_url":null,"creation_ts":1792571243000,"erased":false,"last_seen_ts":1792573484421,"locked":false},{"name":"@alice:matrix.local","user_type":null,"is_guest":false,"admin":false,"deactivated":false,"shadow_banned":false,"displayname":"alice","avatar_url":null,"creation_ts":1792571254000,"erased":false,"last_seen_ts":1792571716414,"locked":false},{"name":"@bob:matrix.local","user_type":null,"is_guest":false,"admin":false,"deactivated":false,"shadow_banned":false,"displayname":"bob",...},{"name":"@carol:matrix.local",...}],"total":4}
响应字段解读(以 admin 为例):
| 字段 | 值(实测) | 含义 |
|---|---|---|
| name | @admin:matrix.local | 完整用户标识 |
| admin | true | 是否服务器管理员 |
| deactivated | false | 是否已注销 |
| shadow_banned | false | 是否被静默封禁(用户无感知地被隔离) |
| locked | false | 是否被锁定(登录被拒) |
| displayname | admin | 显示名 |
| creation_ts | 1792571243000 | 注册时间(毫秒时间戳) |
| last_seen_ts | 1792573484421 | 最后活跃时间(毫秒;从未登录则为 null) |
| is_guest / user_type / erased | false / null / false | 访客标记 / 用户类型 / 数据擦除标记 |
7.2 单用户详情与资料修改(v2)
查询单个用户(字段比列表更全):
curl -s "http://localhost:8141/_synapse/admin/v2/users/@carol:matrix.local?access_token=$AT"
{"name":"@carol:matrix.local","admin":false,"deactivated":false,"locked":false,"shadow_banned":false,"creation_ts":1792573594,"appservice_id":null,"consent_server_notice_sent":null,"consent_version":null,"consent_ts":null,"user_type":null,"is_guest":false,"suspended":false,"displayname":"carol","avatar_url":null,"threepids":[],"external_ids":[],"erased":false,"last_seen_ts":null}
比列表多出的字段:suspended(停用状态)、threepids(绑定的邮箱/手机)、external_ids(外部身份关联)、consent_*(服务条款同意记录)、appservice_id(应用服务归属)。注意细节:单查的 creation_ts 是秒级(1792573594),列表接口是毫秒级(1792573594000)——同一用户两种接口粒度不同,写脚本换算时别踩坑。
修改用户资料(PUT,支持 displayname、avatar_url、admin、locked、deactivated 等字段的部分更新):
curl -s -X PUT "http://localhost:8141/_synapse/admin/v2/users/@carol:matrix.local?access_token=$AT" \
-H 'Content-Type: application/json' \
-d '{"displayname":"Carol Chen"}'
{"name":"@carol:matrix.local","admin":false,"deactivated":false,"locked":false,"shadow_banned":false,"creation_ts":1792573594,"appservice_id":null,"consent_server_notice_sent":null,"consent_version":null,"consent_ts":null,"user_type":null,"is_guest":false,"suspended":false,"displayname":"Carol Chen","avatar_url":null,"threepids":[],"external_ids":[],"erased":false,"last_seen_ts":null}
回显中 displayname 已变为 Carol Chen(PUT 返回修改后的全量用户对象)。用 name 过滤复核生效:
curl -s "http://localhost:8141/_synapse/admin/v2/users?access_token=$AT&from=0&limit=10&name=carol"
{"users":[{"name":"@carol:matrix.local","user_type":null,"is_guest":false,"admin":false,"deactivated":false,"shadow_banned":false,"displayname":"Carol Chen","avatar_url":null,"creation_ts":1792573594000,"erased":false,"last_seen_ts":null,"locked":false}],"total":1}
total:1 且 displayname:"Carol Chen",修改已落库(name=carol 前缀过滤命中,验证了 6.3 的过滤约定)。
7.3 whois:查询用户会话与连接记录
GET /_synapse/admin/v1/whois/{user_id} 返回用户当前全部设备会话与连接痕迹(安全审计常用):
curl -s "http://localhost:8141/_synapse/admin/v1/whois/@alice:matrix.local?access_token=$AT"
{"user_id":"@alice:matrix.local","devices":{"":{"sessions":[{"connections":[{"ip":"::ffff:10.89.59.1","last_seen":1792571716414,"user_agent":"curl/7.81.0"},{"ip":"::ffff:10.89.59.1","last_seen":1792571473855,"user_agent":"curl/7.81.0"},{"ip":"::ffff:10.89.59.1","last_seen":1792571443651,"user_agent":"curl/7.81.0"}]}]}}}
结构解读:devices 以设备 ID 为键(alice 的会话来自脚本直连 API,设备 ID 为空串);每个设备下 sessions[].connections[] 逐条记录 ip(来源 IP)、user_agent(客户端标识)、last_seen(毫秒时间戳)。alice 的三条连接全部来自同一 IP 的 curl 客户端,与本文实测方式一致。排查「账号是否被盗用」时,先看这里有没有陌生 IP/UA。
7.4 管理员标志:查询与提降权
GET/PUT /_synapse/admin/v1/users/{user_id}/admin 专管 admin 标志。四步闭环实测(查询 → 提权 → 复核 → 回退):
# 1) 查询当前标志
curl -s "http://localhost:8141/_synapse/admin/v1/users/@carol:matrix.local/admin?access_token=$AT"
{"admin":false}
# 2) 提权为管理员
curl -s -X PUT "http://localhost:8141/_synapse/admin/v1/users/@carol:matrix.local/admin?access_token=$AT" \
-H 'Content-Type: application/json' -d '{"admin": true}'
{}
# 3) 复核
curl -s "http://localhost:8141/_synapse/admin/v1/users/@carol:matrix.local/admin?access_token=$AT"
{"admin":true}
# 4) 回退为普通用户
curl -s -X PUT "http://localhost:8141/_synapse/admin/v1/users/@carol:matrix.local/admin?access_token=$AT" \
-H 'Content-Type: application/json' -d '{"admin": false}'
{}
空对象 {} 即成功(PUT 返回体无业务字段)。GET 回显从 {"admin":false} 到 {"admin":true} 再回退,闭环成立。提权是高危操作(新管理员可调全部 Admin API),生产环境提权后建议在 7.3 的 whois 里跟踪其会话。
7.5 reset_password:重置用户密码
POST /_synapse/admin/v1/reset_password/{user_id} 请求体带 new_password 即可重置任意本地用户密码。以第八章共享密钥接口创建的测试账号 temp02 为例(创建过程见 8.2,此处先借用它完成重置演示):
curl -s -X POST "http://localhost:8141/_synapse/admin/v1/reset_password/@temp02:matrix.local?access_token=$AT" \
-H 'Content-Type: application/json' \
-d '{"new_password":"n3wPass.42"}'
{}
空对象即成功。验证手段:用新密码走 3.2 的登录流程,回显形态同 3.2(返回新 access_token 即重置生效)。对不存在或已注销的用户执行会报 M_NOT_FOUND(实测回显见第十章错误码表)。
7.6 deactivate:注销用户
POST /_synapse/admin/v1/deactivate/{user_id} 注销用户。以 4.1 实测创建的 d1k01 为例,完成它的生命周期闭环:
curl -s -X POST "http://localhost:8141/_synapse/admin/v1/deactivate/@d1k01:matrix.local?access_token=$AT" \
-H 'Content-Type: application/json' -d '{}'
{"id_server_unbind_result":"success"}
回显含义:id_server_unbind_result: success 表示已向身份服务器解除该用户的三方标识绑定(无身份服务器时也返回 success)。注销后用默认列表复核——d1k01 已不在列表:
curl -s "http://localhost:8141/_synapse/admin/v2/users?access_token=$AT&from=0&limit=20"
{"users":[{"name":"@admin:matrix.local",...},{"name":"@alice:matrix.local",...},{"name":"@bob:matrix.local",...},{"name":"@carol:matrix.local",...}],"total":4}
加 deactivated=true 验证「注销用户仍占用户名」的实测证据(本文全部测试账号均在此列):
curl -s "http://localhost:8141/_synapse/admin/v2/users?access_token=$AT&from=0&limit=20&deactivated=true" \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print([(u["name"], u["deactivated"]) for u in d["users"]], "total:", d["total"])'
[('@admin:matrix.local', False), ('@alice:matrix.local', False), ('@bob:matrix.local', False), ('@carol:matrix.local', False), ('@d1k01:matrix.local', True), ('@temp01:matrix.local', True), ('@temp02:matrix.local', True), ('@temp03:matrix.local', True), ('@temp04:matrix.local', True), ('@temp05:matrix.local', True)] total: 10
⚠️ 注意:注销不可逆且用户名永久占用——实测对已注销账号再执行注册一律报
User ID already taken.(4.1 实测四同源)。注销前确认:该用户是否有需要移交的房间管理权(9.2 可处理其房间)。
八、共享密钥注册接口(/_synapse/admin/v1/register)
8.1 接口机制
这是与 CLI 注册工具同源的 HTTP 注册通道:不依赖登录态,靠 registration_shared_secret 的 HMAC 签名证明管理员身份,适合批量/自动化开户。三步流程:
GET /_synapse/admin/v1/register取一次性 nonce(60 秒内有效、单次使用);- 用共享密钥计算 HMAC-SHA1 摘要:参与签名的四个字段按固定顺序
nonce、username、password、admin|notadmin拼接,字段间以\0(空字节)分隔; POST携带nonce、账号信息与mac(十六进制摘要)提交注册。
8.2 Python 脚本实测
完整脚本(可直接照抄运行,SHARED_SECRET 换成 3.3 实测值):
import json, hmac, hashlib, urllib.request
BASE = "http://localhost:8141"
SHARED_SECRET = "US&am;b2mR3dCi1YrHv1D4AeU01H.Yd,wuIujYL+1,,vH:KG~X"
def post(path, payload):
req = urllib.request.Request(
BASE + path,
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
)
return json.loads(urllib.request.urlopen(req).read())
# 1. GET 取一次性 nonce(60 秒内有效、单次使用)
nonce = json.loads(urllib.request.urlopen(BASE + "/_synapse/admin/v1/register").read())["nonce"]
# 2. 计算 HMAC-SHA1 摘要(参与签名的字段用 \0 分隔,顺序固定)
mac = hmac.new(SHARED_SECRET.encode(), digestmod=hashlib.sha1)
mac.update(nonce.encode()); mac.update(b"\x00")
mac.update(b"temp02"); mac.update(b"\x00")
mac.update(b"q1w2e3r4"); mac.update(b"\x00")
mac.update(b"notadmin") # 注册管理员则传 b"admin"
# 3. 携带 nonce 提交注册
print(post("/_synapse/admin/v1/register", {
"nonce": nonce, "username": "temp02",
"password": "q1w2e3r4", "admin": False, "mac": mac.hexdigest(),
}))
实测运行输出:
python3 d1-register-temp02.py
{'user_id': '@temp02:matrix.local', 'home_server': 'matrix.local', 'access_token': 'syt_dGVtcDAy_iEcdSRLKGVVxTloZxCLO_24K5sJ', 'device_id': 'ERINQFUXPR'}
注册成功且直接返回了新账号的 access_token(该接口独有,CLI 注册不返回 token)——脚本可以接着用这个 token 做初始化操作。注册结果用 7.1 用户列表复核,@temp02:matrix.local 已在列(total 从 4 变 5)。
8.3 排障实录:403 Forbidden
首次尝试时按普通 POST 直接触交注册(未先取 nonce、未带 mac 签名),实测报错(输出节选,仅保留判定关键帧):
Traceback (most recent call last):
...
File "/usr/lib/python3.10/urllib/request.py", line 643, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
定位:该接口不是普通表单提交——服务器要求「先 GET nonce,再按 8.1 的字段顺序 HMAC 签名」,缺 mac 一律 403。解决:改用 8.2 脚本流程(GET nonce → HMAC-SHA1 → POST),实测注册成功。若签名算错同样 403,重点核对三处:字段顺序是否 nonce\0username\0password\0admin|notadmin、分隔符是否空字节 \0、nonce 是否超 60 秒或被复用。
8.4 开户方式对比与测试账号清理
至此三种开户方式全部实测,选型对比:
💡 技术拓展:开户三条路径对比——
方式 入口 前置条件 适用场景 网页注册 Element 注册页 enable_registration: true手工少量开户,用户自助 CLI register_new_matrix_user 服务器本机 registration_shared_secret 初始化建管理员、单次开户 共享密钥注册 API HTTP 远程 registration_shared_secret + HMAC 脚本 批量开户、自动化流水线(直接返回 token) 本系列三种均已实测(网页注册见部署篇 4.6,CLI 见 4.1,API 见 8.2)。生产批量开户选 API 路径:免登录态、可并发、即拿 token;无论哪种,开户后用 7.1 用户列表核对。
temp02 的生命周期收尾:密码已在 7.5 重置为 n3wPass.42,随后按 7.6 同样方式注销:
curl -s -X POST "http://localhost:8141/_synapse/admin/v1/deactivate/@temp02:matrix.local?access_token=$AT" \
-H 'Content-Type: application/json' -d '{}'
{"id_server_unbind_result":"success"} HTTP 200
注销后再查用户列表,temp02 消失(回显同 7.6 默认列表形态,total 回落 4)。
九、房间、令牌与媒体管理域 API
9.1 房间列表
GET /_synapse/admin/v1/rooms 返回本地服务器上的全部房间(分页):
curl -s "http://localhost:8141/_synapse/admin/v1/rooms?access_token=$AT&from=0&limit=10"
{"offset":0,"rooms":[{"room_id":"!QxXyaG7NjuhTQvRBskG5B65awcmIpke22rIF_bmStrk","name":"\u7814\u53d1\u90e8\u4ea4\u6d41","canonical_alias":null,"joined_members":2,"joined_local_members":2,"version":"12","creator":"@admin:matrix.local","encryption":null,"federatable":true,"public":false,"join_rules":"invite","guest_access":"can_join","history_visibility":"shared","state_events":8,"room_type":null}],"total_rooms":1}
字段解读:name 的 \u7814\u53d1\u90e8\u4ea4\u6d41 是 JSON Unicode 转义,即「研发部交流」(部署篇 4.10 创建的房间);room_id 以 ! 开头是房间全局唯一标识(删除、移交都靠它);join_rules: invite 私密邀请制、public: false 不公开;joined_members/joined_local_members 分别是总成员与本服成员数;version: "12" 是房间协议版本;state_events: 8 状态事件数。该接口是「房间治理」的入口:先列表拿到 room_id,再执行 9.2 的删除。
9.2 删除房间
DELETE /_synapse/admin/v1/rooms/{room_id} 踢出全部成员并清除房间。先创建一个演示房间(走 Client-Server API 建房):
curl -s -X POST "http://localhost:8141/_matrix/client/v3/createRoom?access_token=$AT" \
-H 'Content-Type: application/json' \
-d '{"name":"D1 演示房间","preset":"private_chat"}'
{"room_id":"!NnxSLDm-5mdPEduPa-LilLX52hmSpENc_sRaehj3qa4"}
再从 Admin API 删除它(请求体 block 是否封锁房间 ID 防重建、purge 是否彻底清除历史):
curl -s -X DELETE "http://localhost:8141/_synapse/admin/v1/rooms/!NnxSLDm-5mdPEduPa-LilLX52hmSpENc_sRaehj3qa4?access_token=$AT" \
-H 'Content-Type: application/json' \
-d '{"block":false,"purge":true}'
{"kicked_users":["@admin:matrix.local"],"failed_to_kick_users":[],"local_aliases":[],"new_room_id":null}
回显解读:kicked_users 列出被踢成员;failed_to_kick_users 留空即全部踢出成功;local_aliases 是被移除的本地别名;new_room_id 仅在「迁移到新房间」场景返回(本文 purge 删除为 null)。删除后复核列表终态:
curl -s "http://localhost:8141/_synapse/admin/v1/rooms?access_token=$AT&from=0&limit=10"
{"offset":0,"rooms":[{"room_id":"!QxXyaG7NjuhTQvRBskG5B65awcmIpke22rIF_bmStrk","name":"\u7814\u53d1\u90e8\u4ea4\u6d41","canonical_alias":null,"joined_members":2,"joined_local_members":2,"version":"12","creator":"@admin:matrix.local","encryption":null,"federatable":true,"public":false,"join_rules":"invite","guest_access":"can_join","history_visibility":"shared","state_events":8,"room_type":null}],"total_rooms":1}
total_rooms 回落到 1(只剩部署篇创建的研发部交流房间),演示房间已清除。多成员房间同样适用——本文实测删除一个两名成员的历史遗留房间,回显 kicked_users 同时列出两名成员:
{"kicked_users":["@admin:matrix.local","@alice:matrix.local"],"failed_to_kick_users":[],"local_aliases":[],"new_room_id":null}
⚠️ 注意:
purge: true连同历史事件一起清除,不可恢复;block: true会封锁该 room_id 防止再次创建,处置违规房间时才启用。
9.3 注册令牌管理
注册令牌(registration token)是 Element 注册页支持的一种自助注册凭据:持有有效令牌才能完成注册,适合「受控开放注册」。管理接口一组五步闭环实测。
查询令牌列表(初始为空):
curl -s "http://localhost:8141/_synapse/admin/v1/registration_tokens?access_token=$AT"
{"registration_tokens":[]}
新建令牌(uses_allowed 限用 5 次;不传该字段则为无限次):
curl -s -X POST "http://localhost:8141/_synapse/admin/v1/registration_tokens/new?access_token=$AT" \
-H 'Content-Type: application/json' -d '{"uses_allowed": 5}'
{"token":"ja9RorlXjSd.D-q9","uses_allowed":5,"pending":0,"completed":0,"expiry_time":null}
复核列表:
curl -s "http://localhost:8141/_synapse/admin/v1/registration_tokens?access_token=$AT"
{"registration_tokens":[{"token":"ja9RorlXjSd.D-q9","uses_allowed":5,"pending":0,"completed":0,"expiry_time":null}]}
字段解读:token 是注册页要填的令牌串;uses_allowed 总可用次数;pending 已开始注册但未完成的次数;completed 已完成注册的次数;expiry_time 过期时间戳(null 不过期)。
删除令牌(令牌串从上一步回显提取):
curl -s -X DELETE "http://localhost:8141/_synapse/admin/v1/registration_tokens/ja9RorlXjSd.D-q9?access_token=$AT"
{}
终态复核:
curl -s "http://localhost:8141/_synapse/admin/v1/registration_tokens?access_token=$AT"
{"registration_tokens":[]}
从空到建到删的闭环完成。注意:注册令牌模式与 enable_registration 开关的配合关系(开启令牌注册的配置改法)见 《Synapse/Element v1.163.0 配置参数详解》第四章。
9.4 用户媒体统计
GET /_synapse/admin/v1/statistics/users/media 按用户统计媒体文件占用(容量治理用):
curl -s "http://localhost:8141/_synapse/admin/v1/statistics/users/media?access_token=$AT&from=0&limit=5"
{"users":[],"total":0}
本文环境尚未上传任何媒体文件,列表为空(total: 0)。有媒体后,users 数组逐用户返回 user_id、media_length(累计字节数)、media_count(文件数)等字段并按占用排序,配合分页可快速定位「谁占满了磁盘」。
十、错误码速查与排障
Admin API 的错误响应统一为含 errcode(机器可读错误码)与 error(人读描述)两个字段的 JSON 对象。以下每一条都在本文环境实测复现:
一、未带 token(HTTP 401):
curl -s "http://localhost:8141/_synapse/admin/v2/users" -w '\nHTTP %{http_code}\n'
{"errcode":"M_MISSING_TOKEN","error":"Missing access token"}
HTTP 401
二、token 错误或已失效(HTTP 401):
curl -s "http://localhost:8141/_synapse/admin/v2/users?access_token=BADTOKEN" -w '\nHTTP %{http_code}\n'
{"errcode":"M_UNKNOWN_TOKEN","error":"Invalid access token passed.","soft_logout":false}
HTTP 401
处理:重新按 3.2 登录取新 token。soft_logout:false 表示服务端已直接失效该会话。
三、端点路径或方法错误(HTTP 404):
curl -s "http://localhost:8141/_synapse/admin/v1/not_exist?access_token=$AT" -w '\nHTTP %{http_code}\n'
{"errcode":"M_UNRECOGNIZED","error":"Unrecognized request"}
HTTP 404
本文实测的另一处同码场景:注销用户时把路径写错(非 /deactivate/),同样返回 M_UNRECOGNIZED——修正为 POST /_synapse/admin/v1/deactivate/{user_id} 后成功。见到 M_UNRECOGNIZED 先核对路径拼写与 HTTP 方法。
四、资源不存在(HTTP 404)——查询单用户接口对不存在用户:
curl -s "http://localhost:8141/_synapse/admin/v2/users/@nouser:matrix.local?access_token=$AT" -w '\nHTTP %{http_code}\n'
{"errcode":"M_NOT_FOUND","error":"User not found"}
HTTP 404
reset_password 对不存在/未建成用户同样报 M_NOT_FOUND(实测回显 {"errcode":"M_NOT_FOUND","error":"Unknown user"})——本文实测在共享密钥注册 403 失败、账号未建成时重置其密码触发。
五、共享密钥注册缺签名(HTTP 403):直接 POST 不带 nonce/mac 时返回裸 HTTP 403: Forbidden(无 errcode 结构),完整排障过程见 8.3。
六、登录限流(M_LIMIT_EXCEEDED):连续多次登录触发,实测回显 {"errcode":"M_LIMIT_EXCEEDED","error":"Too Many Requests","retry_after_ms":274398}——retry_after_ms 提示需等待约 274 秒。放宽方案(rc_login 参数调整与实测)见 《Synapse/Element v1.163.0 配置参数详解》第四章与部署篇排障节。
速查总表:
| errcode / 状态 | HTTP | 触发场景(实测) | 处理 |
|---|---|---|---|
| M_MISSING_TOKEN | 401 | 请求未带 access_token | 按 3.2 登录并携带 token |
| M_UNKNOWN_TOKEN | 401 | token 错误/已失效 | 重新登录取新 token |
| M_UNRECOGNIZED | 404 | 端点路径拼错 / 方法用错 | 核对路径(如 deactivate 尾段)与方法 |
| M_NOT_FOUND | 404 | v2 单查不存在用户;reset_password 目标用户不存在 | 核对 user_id 是否存在(用 7.1 列表确认) |
| 403 Forbidden | 403 | 共享密钥注册缺 nonce/mac 或签名错误 | 按 8.1 机制重签(字段顺序、\0 分隔、60 秒时效) |
| M_LIMIT_EXCEEDED | — | 登录触发限流 | 等 retry_after_ms 或放宽 rc_login |
另有一个易困惑点实测澄清:whois 对不存在的用户返回 HTTP 200({"user_id":"@nouser:matrix.local","devices":{"":{"sessions":[{"connections":[]}]}}},连接列表为空)——它不做存在性校验;而 v2 单用户详情对不存在用户返回 404 M_NOT_FOUND。判断用户是否存在请用 v2 接口(7.1/7.2),不要用 whois 的状态码。
十一、注意事项
- 凭据分层保管:
registration_shared_secret等同半个管理员(可任意开户);管理员 access_token 等同账号本体。两者都不进代码仓库与日志;token 疑似泄露时轮换macaroon_secret_key使全部会话失效。 - 不可逆操作先确认:
deactivate(用户名永久占用)、DELETE rooms(purge 清历史)、注册令牌删除均无回收站;批量脚本先在单账号上验证再放量。 - CLI 与 API 的适用边界:CLI 工具要求在服务器本机执行(读配置/密钥文件),Admin API 远程可用;把 CLI 包装进自动化脚本不如直接用 Admin API 稳定(接口有版本契约,CLI 参数随版本变动风险更高)。
- 版本绑定:本文全部端点行为以 Synapse v1.163.0 实测为准;Admin API 演进较快(如用户管理 v2 相对 v1 的字段扩充),跨版本升级后建议先跑 6.2 的 server_version 与 7.1 用户列表做冒烟验证。
- v1/v2 混用注意时间戳粒度:用户列表(毫秒
creation_ts)与单用户详情(秒creation_ts)粒度不同(7.2 实测),脚本换算要区分。 - 限流同样约束管理调用:连续登录取 token 会触发 M_LIMIT_EXCEEDED(第十章实测),自动化脚本控制请求节奏,或按 C1 调整 rc_login 参数。
十二、常见问题
Q1:CLI 工具提示找不到命令怎么办?
先分清安装形态:Docker 发行包内工具不在宿主机 PATH,用 docker compose exec synapse <工具名>(1.1);apt 源安装的工具名可能带路径(/usr/bin/register_new_matrix_user);pip 源码安装在虚拟环境的 bin 目录。共同点是 -c 指向的配置文件必须可读且含 registration_shared_secret(3.3 验证)。
Q2:注册报 User ID already taken.,但用户列表里没有这个用户?
该用户名已被注销账号占用:v2 用户列表默认不返回已注销用户,加 deactivated=true 即现形(7.6 实测回显:默认列表 total 4,加参后 total 10)。注销不可逆、用户名不可复用——换新用户名,或评估该历史账号是否需要恢复数据后重建。
Q3:共享密钥注册接口一直 403 Forbidden?
按 8.3 排障三步核对:① 是否先 GET 了 nonce 且 60 秒内提交、未复用;② HMAC 字段顺序是否严格 nonce\0username\0password\0admin|notadmin、分隔符是空字节 \0(Python 用 b"\x00");③ 共享密钥是否与 homeserver.yaml 当前值一致(轮换过就取新值)。用 8.2 脚本逐段比对最快。
Q4:Admin API 返回 M_MISSING_TOKEN / M_UNKNOWN_TOKEN?
前者是根本没带 token(检查 ?access_token= 是否拼上、或 Bearer 头是否正确);后者是 token 值错误或已失效——重新按 3.2 登录取新 token。两个错误码的实测回显见第十章第一、二条。
Q5:whois 查不存在的用户也返回 200,正常吗? 正常(第十章实测澄清):whois 不做存在性校验,返回空连接列表;存在性判断以 v2 单用户详情(404 M_NOT_FOUND)或用户列表为准。
Q6:synapse_port_db 迁移前必须做什么?
帮助文本明确要求 SQLite 库必须是停服后的快照副本(不能迁移正在使用的库):先停 Synapse → 复制 homeserver.db → 对副本执行迁移 → 改配置指向 PostgreSQL → 启动。--batch-size 默认 1000,大库可调大加速。本文环境未部署 PostgreSQL,未执行全量搬运(5.4 已说明)。
Q7:hash_password 每次输出都不一样,是不是错了? 正常。bcrypt 每次生成随机盐,同一密码两次实测输出不同(4.2 实测两组哈希),都能通过服务器校验。比对密码正确与否的唯一手段是登录验证,不是字符串比较。
十三、参考链接
- 本系列实操篇:《Synapse/Element v1.163.0 介绍与选型指南》、《Synapse/Element v1.163.0 Docker Compose 部署指南》、《Synapse/Element v1.163.0 配置参数详解》
- Synapse Admin API 官方文档(总览与认证约定):https://element-hq.github.io/synapse/latest/usage/administration/admin_api/
- 用户管理 API(v2 用户列表/详情/修改)官方文档:https://element-hq.github.io/synapse/latest/admin_api/user_admin_api.html
- 共享密钥注册接口官方文档:https://element-hq.github.io/synapse/latest/admin_api/register_api.html
- 房间管理 API 官方文档:https://element-hq.github.io/synapse/latest/admin_api/rooms.html
- homeserver.yaml 配置文档(哈希与限流参数):https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html
(官方参考链接探活日期:2026-10-22,均为 HTTP 200 可访问。)