Synapse/Element v1.163.0 Admin API 与 CLI 工具详解

逐条实测 Synapse v1.163.0 全部内置 CLI 工具与 Admin API:注册、密码哈希、签名密钥、配置生成、数据库迁移工具参数详解,用户、房间、注册令牌、共享密钥注册接口全流程闭环与错误码排障实录。

Synapse/Element即时通信MatrixSynapse2026/10/22

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)服务器环境
Synapsev1.163.0(2026-10-14 发布)matrixdotorg/synapse 官方发行包
Element Webv1.12.32(2026-10-16 发布)同系列部署,本文不直接操作
server_namematrix.local用户标识域名部分(@admin:matrix.local)
主配置文件/opt/synapse/data/homeserver.yamlCLI 工具以 -c 读取它
CLI 调用形态docker compose exec synapse <工具名>工作目录 /opt/synapse,见 1.1 说明
Admin API 基址http://localhost:8141端口映射见部署篇
演示账号admin(管理员)/ alice / bob / carol,密码 q1w2e3r4admin 由部署篇 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_dbSQLite → 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 弱于新一代大量存量系统的默认选择
Argon2id2015 密码哈希竞赛冠军,抗 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完整用户标识
admintrue是否服务器管理员
deactivatedfalse是否已注销
shadow_bannedfalse是否被静默封禁(用户无感知地被隔离)
lockedfalse是否被锁定(登录被拒)
displaynameadmin显示名
creation_ts1792571243000注册时间(毫秒时间戳)
last_seen_ts1792573484421最后活跃时间(毫秒;从未登录则为 null)
is_guest / user_type / erasedfalse / 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 签名证明管理员身份,适合批量/自动化开户。三步流程:

  1. GET /_synapse/admin/v1/register 取一次性 nonce(60 秒内有效、单次使用);
  2. 用共享密钥计算 HMAC-SHA1 摘要:参与签名的四个字段按固定顺序 nonce、username、password、admin|notadmin 拼接,字段间以 \0(空字节)分隔;
  3. 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初始化建管理员、单次开户
共享密钥注册 APIHTTP 远程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_TOKEN401请求未带 access_token按 3.2 登录并携带 token
M_UNKNOWN_TOKEN401token 错误/已失效重新登录取新 token
M_UNRECOGNIZED404端点路径拼错 / 方法用错核对路径(如 deactivate 尾段)与方法
M_NOT_FOUND404v2 单查不存在用户;reset_password 目标用户不存在核对 user_id 是否存在(用 7.1 列表确认)
403 Forbidden403共享密钥注册缺 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 的状态码。

十一、注意事项

  1. 凭据分层保管:registration_shared_secret 等同半个管理员(可任意开户);管理员 access_token 等同账号本体。两者都不进代码仓库与日志;token 疑似泄露时轮换 macaroon_secret_key 使全部会话失效。
  2. 不可逆操作先确认:deactivate(用户名永久占用)、DELETE rooms(purge 清历史)、注册令牌删除均无回收站;批量脚本先在单账号上验证再放量。
  3. CLI 与 API 的适用边界:CLI 工具要求在服务器本机执行(读配置/密钥文件),Admin API 远程可用;把 CLI 包装进自动化脚本不如直接用 Admin API 稳定(接口有版本契约,CLI 参数随版本变动风险更高)。
  4. 版本绑定:本文全部端点行为以 Synapse v1.163.0 实测为准;Admin API 演进较快(如用户管理 v2 相对 v1 的字段扩充),跨版本升级后建议先跑 6.2 的 server_version 与 7.1 用户列表做冒烟验证。
  5. v1/v2 混用注意时间戳粒度:用户列表(毫秒 creation_ts)与单用户详情(秒 creation_ts)粒度不同(7.2 实测),脚本换算要区分。
  6. 限流同样约束管理调用:连续登录取 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 实测两组哈希),都能通过服务器校验。比对密码正确与否的唯一手段是登录验证,不是字符串比较。

十三、参考链接

  1. 本系列实操篇:《Synapse/Element v1.163.0 介绍与选型指南》、《Synapse/Element v1.163.0 Docker Compose 部署指南》、《Synapse/Element v1.163.0 配置参数详解》
  2. Synapse Admin API 官方文档(总览与认证约定):https://element-hq.github.io/synapse/latest/usage/administration/admin_api/
  3. 用户管理 API(v2 用户列表/详情/修改)官方文档:https://element-hq.github.io/synapse/latest/admin_api/user_admin_api.html
  4. 共享密钥注册接口官方文档:https://element-hq.github.io/synapse/latest/admin_api/register_api.html
  5. 房间管理 API 官方文档:https://element-hq.github.io/synapse/latest/admin_api/rooms.html
  6. homeserver.yaml 配置文档(哈希与限流参数):https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html

(官方参考链接探活日期:2026-10-22,均为 HTTP 200 可访问。)