PixelFed 0.15.2 常用 CLI 命令详解

系统梳理 PixelFed v0.15.2 的 artisan 命令族(账号/迁移/队列与 Horizon/定时任务/媒体维护/数据导入/存储与密钥/站点诊断与维护模式),每条核心命令给出签名、实测回显与行为解读,并沉淀复跑幂等性与退出码差异。

PixelFedPixelFed自托管2026/10/27

PixelFed 0.15.2 常用 CLI 命令详解

目标:系统梳理 PixelFed v0.15.2 的 artisan 命令体系(账号管理、数据库迁移、队列与 Horizon、定时任务、媒体维护、数据导入、存储与密钥初始化、站点诊断与维护模式),每条核心命令都给出「签名 → 实测执行 → 回显 → 行为解读」的完整闭环。已在 Ubuntu 22.04 服务器(IP 192.168.146.128,端口 8135)逐条实测通过,包括命令复跑的幂等/报错行为与退出码。

一、环境信息

项目实测值
操作系统Ubuntu 22.04(x86_64)
PixelFedv0.15.2(官方编排形态部署)
Laravel Framework13.38.0(php artisan --version 实测)
PHP(CLI)8.5.12(php artisan about 实测)
数据库MariaDB 11.8
缓存/队列Redis 8
部署目录/opt/pixelfed
访问地址http://192.168.146.128:8135
演示账号admin / q1w2e3r4(管理员);demotest、adminflag(第四章实测创建,密码同为 q1w2e3r4)

本文所有命令均在部署目录 /opt/pixelfed 下执行,php artisan 命令通过编排内执行形态调用(同《PixelFed 0.15.2 Docker Compose 部署指南》4.6 节的方式),下文示例统一简写为 docker compose exec pixelfed php artisan <命令>。

二、工具概览

PixelFed 基于 Laravel 框架,其 CLI 入口是框架自带的 artisan 工具——站点初始化、账号管理、队列维护、数据导入、故障诊断等全部运维动作都通过 php artisan <命令> 完成。本章先给出命令体系的自省方法与全景矩阵,后续章节按命令族逐一实测。

2.1 命令自省三件套

artisan 自身提供三个自省命令,遇到任何不熟悉的命令先用它们查签名,无需查阅外部文档:

cd /opt/pixelfed
docker compose exec pixelfed php artisan --version

实测回显:

Laravel Framework 13.38.0
# 列出全部命令(按命名空间分组)
docker compose exec pixelfed php artisan list

实测回显(输出节选,实测首尾):

Laravel Framework 13.38.0

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display help for the given command. When no command is given display help for the list command
      --silent          Do not output any message
  -q, --quiet           Only errors are displayed. All other output is suppressed
  -V, --version         Display this application version
      --ansi|--no-ansi  Force (or disable --no-ansi) ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env[=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  about                                     Display basic information about your application
  clear-compiled                            Remove the compiled class file
  completion                                Dump the shell completion script
  db                                        Start a new database CLI session
  dev                                       Run the dev processes
  docs                                      Access the Laravel documentation
  down                                      Put the application into maintenance / demo mode
  env                                       Display the current framework environment
  help                                      Display help for a command
  horizon                                   Start a master supervisor in the foreground
  install                                   CLI Installer
  list                                      List commands
  migrate                                   Run the database migrations
  optimize                                  Cache framework bootstrap, configuration, and metadata to increase performance
  reload                                    Reload running services
  serve                                     Serve the application on the PHP development server
  test                                      Run the application tests
  tinker                                    Interact with your application
  ui                                        Swap the front-end scaffolding for the application
  up                                        Bring the application out of maintenance mode
  update                                    Run pixelfed schema updates between versions.
 admin
……(中间为 user / media / import / horizon / queue 等命名空间分组的全部命令,约 300 行)……
 webpush
  webpush:vapid                             Generate VAPID keys.
# 查看单条命令的签名(参数与选项、默认值)
docker compose exec pixelfed php artisan user:create --help

实测回显(输出节选,实测首尾):

Description:
  Create a new user

Usage:
  user:create [options]

Options:
      --name[=NAME]                    
      --username[=USERNAME]            
      --email[=EMAIL]                  
      --password[=PASSWORD]            
      --is_admin[=IS_ADMIN]             [default: "0"]
      --confirm_email[=CONFIRM_EMAIL]   [default: "0"]
  -h, --help                           Display help for the given command. When no command is given display help for the list command
……(以下为 Laravel 通用全局选项,各命令相同)……

2.2 命令族全景矩阵

按 php artisan list 实测输出归纳,v0.15.2 的命令按命名空间分为以下命令族(条目数为实测清点):

命令族条目数用途代表命令
user13账号生命周期管理(创建/提权/密码诊断/注销)user:create、user:admin
migrate7数据库迁移migrate、migrate:status
horizon17队列消费器(Horizon)管理horizon:status、horizon:list
queue14队列作业管理(失败重试/清空/监控)queue:failed、queue:retry
schedule8定时任务查看与控制schedule:list
media5媒体维护(优化/垃圾回收/修复)media:optimize、media:gc
import2数据导入(城市/自定义表情)import:cities、import:emojis
storage3存储符号链接与清理storage:link、storage:maintenance
passport5OAuth 密钥与客户端管理passport:keys、passport:client
instance1实例 Actor(联邦身份)生成instance:actor
gc3周期性垃圾回收gc:sessions、gc:failedjobs
story1过期故事清理story:gc
status8账号/媒体/实例元数据诊断status:user、status:media
fix6数据修复(用户名/点赞数/头像等)fix:usernames、fix:likes
app26实例运维与联邦诊断app:federation、app:home-feed-rebuild
admin6管理员维护(计数修正/存储迁移)admin:fixPostCounts
config / db / key4 / 5 / 1配置查看 / 数据库信息 / 应用密钥config:show、db:table、key:generate

解读:日常运维高频的是 user、media、gc、schedule、horizon 五族;初始化阶段关键是 migrate、storage:link、passport:keys、import:cities、instance:actor;排障首选 app:federation 与 status 族。本文第四章按此优先级展开。

三、前置条件

  1. 已完成 v0.15.2 部署且迁移通过——迁移状态确认命令与回显见 4.2 节(实测 268 个迁移全部 Ran);部署与 5 个服务健康状态确认见《PixelFed 0.15.2 Docker Compose 部署指南》4.7 节;
  2. 已有管理员账号 admin / q1w2e3r4(创建过程见部署指南 4.6 节);
  3. 明确「编排内执行形态」:本文所有 docker compose exec pixelfed php artisan ... 都在部署目录 /opt/pixelfed 下执行,等价于在应用运行环境内以正确的工作目录与用户身份执行 artisan;
  4. 部分命令(user:admin、user:checkpassword)为交互式或需标准输入,自动化调用方式见 4.1 节实测与第五章注意事项。

四、核心命令族详解

4.1 账号管理(user 命令族)

user 命令族覆盖账号从创建到注销的完整生命周期。本节以一组连续实测走通「创建 → 查表 → 诊断 → 提权 → 邮箱确认」全链路。

user:create 创建用户(签名见 2.1 节):

docker compose exec pixelfed php artisan user:create \
  --name="Demo Tester" --username=demotest \
  --email=demotest@example.com --password=q1w2e3r4

实测回显:

Creating a new user...
Successfully created user!

user:table 查看用户表(创建前后各执行一次):

docker compose exec pixelfed php artisan user:table

创建前实测回显:

+----+----------+-------+-----------------------------+
| ID | Username | Name  | Registered                  |
+----+----------+-------+-----------------------------+
| 1  | admin    | admin | 2026-10-26T16:45:32.000000Z |
+----+----------+-------+-----------------------------+

创建后实测回显:

+----+----------+-------------+-----------------------------+
| ID | Username | Name        | Registered                  |
+----+----------+-------------+-----------------------------+
| 2  | demotest | Demo Tester | 2026-10-26T17:36:26.000000Z |
| 1  | admin    | admin       | 2026-10-26T16:45:32.000000Z |
+----+----------+-------------+-----------------------------+

user:show 查看单用户概况:

docker compose exec pixelfed php artisan user:show demotest

实测回显:

User ID: 2
Username: demotest
Email: demotest@example.com
Joined: 0 seconds ago
Status Count: 0

user:checkpassword 密码诊断(只读):该命令验证候选密码与库中哈希是否匹配,并给出登录被拒的诊断线索。候选密码经标准输入传入(隐藏输入、不落存储),自动化场景用管道:

echo 'q1w2e3r4' | docker compose exec -T pixelfed php artisan user:checkpassword demotest

实测回显(正确密码,全文):

User: demotest (id 2)
Email on record: demotest@example.com

Login authenticates by EMAIL + password (LoginController defaults to the "email" field).

Email is unique in the users table. ✓
The web guard resolves to this same row. ✓

Stored hash algorithm: bcrypt
Stored hash cost: 10

 Enter the password you are trying to log in with (hidden, not stored):
 > 


✓ PASSWORD MATCHES the stored hash for this row.
If web login still fails with this exact password + email "demotest@example.com", the problem is NOT the password:
   - check for a duplicate email row above,
   - confirm you are typing the email exactly (no trailing spaces),
   - confirm the app server and CLI share the same database & APP_KEY,
   - check for login throttling (5 failed attempts / 60 min lockout).

输入错误密码 wrong-pass-123 时,前段输出(用户定位、哈希算法等 10 行)完全相同,差异为结尾判定(实测节选):

✗ PASSWORD DOES NOT MATCH the stored hash for this row.
Re-run: php artisan user:setpassword demotest and set it again, then re-check here.
If it still will not match after setting, the CLI and web app likely point at different databases.

解读:该命令不改动任何数据,适合在用户报「登录不上」时先行定位——若密码匹配仍被拒,回显已给出四条后续排查方向(重复邮箱、输入误差、APP_KEY 不一致、登录节流 5 次/60 分钟锁定)。

user:admin 提权(交互确认):

echo yes | docker compose exec -T pixelfed php artisan user:admin demotest

实测回显:

Found username: demotest

 Add admin privileges to this user? (yes/no) [no]:
 > 
Successfully changed permissions!

⚠️ user:create 的 --is_admin 选项实测不持久化:签名虽有 --is_admin[=IS_ADMIN],但传入 1 后查库确认 is_admin 仍为 false(v0.15.2 实测行为)。完整复测:先用 --is_admin=1 创建 adminflag,随即用 tinker 查询:

docker compose exec pixelfed php artisan user:create \
  --name="Admin Flag" --username=adminflag \
  --email=adminflag@example.com --password=q1w2e3r4 --is_admin=1
docker compose exec pixelfed php artisan tinker --execute='$u=\App\Models\User::where("username","adminflag")->first(); echo "is_admin="; var_export($u->is_admin);'

实测回显:

Creating a new user...
Successfully created user!

is_admin=false

再用 user:admin 提权后复查(前半段回显同上,略):

is_admin=true

结论:提权统一走 user:admin,不要依赖 --is_admin 选项。

user:verifyemail 跳过邮箱验证:

docker compose exec pixelfed php artisan user:verifyemail demotest

实测回显:

Successfully verified email address for demotest

user 命令族全量表(用途取自各命令实测 --help 描述):

命令用途
user:create创建新用户
user:admin设为/移除管理员(交互确认)
user:checkpassword只读密码诊断(stdin 传候选密码)
user:setpassword重设密码(安全提示输入,bcrypt 哈希)
user:show查看用户概况
user:table显示最新用户列表
user:verifyemail标记用户邮箱已验证
user:2fa关闭指定用户的两步验证
user:delete删除账号
user:unsuspend解除本地用户封禁
user:avatar-delete删除头像并重置为默认
user:app-magic-link为应用内注册未收确认邮件的用户获取魔法链接
user:storage:recalculate按实际媒体重算 users.storage_used(修复配额计数)

4.2 数据库迁移(migrate 命令族)

migrate 命令族管理数据库结构版本。部署初始化后最常用的是状态确认;fresh/reset/rollback 属破坏性命令,生产环境慎用(见第五章)。

migrate:status 确认迁移状态:

docker compose exec pixelfed php artisan migrate:status | tail -5
docker compose exec pixelfed php artisan migrate:status | grep -c 'Ran'

实测回显:

  2026_09_30_042509_add_block_sync_url_to_instances_table ............ [1] Ran  
  2026_10_06_000001_normalize_legacy_user_languages .................. [1] Ran  
  2026_10_06_000001_widen_remote_url_on_avatars_table ................ [1] Ran  
  2026_10_07_000001_normalize_legacy_user_filter_morph_types ......... [1] Ran  
268

解读:268 个迁移全部 [1] Ran(批次 1)且无 Pending,即结构初始化完成。该命令也是升级版本后的第一验证项。

migrate 命令族全量表:

命令用途生产建议
migrate执行待运行迁移升级后必执行
migrate:status显示每个迁移的状态日常确认用
migrate:rollback回滚上一次迁移慎用
migrate:reset回滚全部迁移破坏性,禁用于生产
migrate:refresh重置并重跑全部迁移破坏性,禁用于生产
migrate:fresh删表后重跑全部迁移破坏性,禁用于生产
migrate:install创建迁移仓库表初始化自动完成

4.3 队列与 Horizon(horizon / queue 命令族)

PixelFed 的缩略图生成、媒体优化、联邦投递等异步任务由 Horizon 消费 Redis 队列完成,Horizon 停摆会直接表现为「上传成功但缩略图不生成」(见《PixelFed 0.15.2 配置参数详解》第七章 Q4)。

horizon:status 确认消费器运行:

docker compose exec pixelfed php artisan horizon:status

实测回显:

INFO  Horizon is running.  

horizon:list 查看部署实例与监督器:

docker compose exec pixelfed php artisan horizon:list

实测回显:

+-------------------+-----+-----------------------------------------------------------------------------------------------------+---------+
| Name              | PID | Supervisors                                                                                         | Status  |
+-------------------+-----+-----------------------------------------------------------------------------------------------------+---------+
| a261455df413-iJ2A | 1   | supervisor-priority, supervisor-fanout, supervisor-deliver, supervisor-media, supervisor-background | running |
+-------------------+-----+-----------------------------------------------------------------------------------------------------+---------+

解读:当前 Horizon 主监督器运行中,下辖 priority / fanout / deliver / media / background 五个监督器,分别消费不同队列组;各队列的实时积压可在 4.8 节 app:federation 输出的 QUEUES 表中看到(default/high/shared/follow/inbox/delete/story/feed/low/move 十个队列均 Worker=yes、Pending=0)。

queue:failed 查看失败作业:

docker compose exec pixelfed php artisan queue:failed

实测回显:

INFO  No failed queue jobs found.  

常用 horizon/queue 命令速查(清单取自实测 php artisan list,其中 horizon:status、horizon:list、queue:failed 已实测):

命令用途
horizon:terminate通知主监督器优雅退出(改动配置/代码后重启消费器用)
horizon:pause / horizon:continue暂停/恢复作业消费
horizon:snapshot立即存储一次队列指标快照(调度表每 5 分钟自动执行)
horizon:forget删除单条失败作业
horizon:clear清空指定队列的作业
queue:retry重试失败作业(配合 queue:failed 使用)
queue:flush清空失败作业表
queue:monitor监控指定队列的积压规模

4.4 定时任务(schedule 命令族)

PixelFed 内置一批周期维护任务(媒体优化、垃圾回收、指标快照等),由常驻调度进程按 cron 表达式触发(该进程在部署编排中独立运行,见部署指南 4.5 节的服务构成)。schedule:list 列出全部计划任务及下次执行时间:

docker compose exec pixelfed php artisan schedule:list

实测回显(全文):

  40  *     * * *  php artisan media:optimize ... Next Due: 3 minutes from now
  5   *     * * *  php artisan media:gc ........ Next Due: 28 minutes from now
  */5 *     * * *  php artisan horizon:snapshot . Next Due: 3 minutes from now
  */5 *     * * *  php artisan story:gc ......... Next Due: 3 minutes from now
  0   3     * * *  php artisan gc:failedjobs ...... Next Due: 9 hours from now
  41  9     * * *  php artisan gc:passwordreset .. Next Due: 16 hours from now
  0   13,23 * * *  php artisan gc:sessions ........ Next Due: 5 hours from now
  15  4     * * *  php artisan storage:maintenance  Next Due: 10 hours from now
  20  4     * * 2  php artisan app:weekly-instance-scan  Next Due: 10 hours from now
  0   1     * * *  php artisan app:cleanup-expired-app-registrations  Next Due: 7 hours from now
  20  */4   * * *  php artisan passport:purge ..... Next Due: 2 hours from now
  33  */6   * * *  php artisan notifications:prune-old  Next Due: 56 minutes from now
  0   13,22 * * *  php artisan app:transform-imports  Next Due: 4 hours from now
  51  *     * * *  php artisan app:import-upload-garbage-collection  Next Due: 14 minutes from now
  37  *     * * *  php artisan app:import-remove-deleted-accounts  Next Due: 5 seconds from now
  32  1,13  * * *  php artisan app:import-upload-clean-storage  Next Due: 7 hours from now
  25  *     * * *  php artisan app:hashtag-cached-count-update  Next Due: 48 minutes from now
  25  */6   * * *  php artisan app:account-post-count-stat-update  Next Due: 48 minutes from now
  45  1,13  * * *  php artisan app:instance-update-total-local-posts  Next Due: 8 hours from now
  40  3     * * *  php artisan federation:block-sync-reconcile  Next Due: 10 hours from now

解读(关键行):媒体优化每小时第 40 分钟、媒体垃圾回收每小时第 5 分钟、指标快照与故事清理每 5 分钟、失败作业清理每日 03:00、会话清理每日 13/23 点、存储维护每日 04:15、Passport 令牌清理每 4 小时。也就是说 4.5/4.9 节的维护命令平时无需手工执行,手工执行主要用于补跑与排障。

schedule 族其余命令(schedule:run 立即执行到期任务、schedule:work 前台常驻、schedule:pause/resume 暂停恢复、schedule:interrupt 中断当前运行、schedule:test 试运行指定任务、schedule:clear-cache 清理调度互斥缓存)按 --help 签名使用即可。

4.5 媒体维护(media 命令族)

media:optimize 补跑媒体优化:找出尚未优化的媒体并入队,由 Horizon 消费。签名支持 --limit(单次入队上限,实测默认 1000):

docker compose exec pixelfed php artisan media:optimize

实测回显:

Queued 0 media candidates.

解读:0 表示当前无待优化积压(此前上传的媒体均已由队列完成优化,媒体 processed 状态可在配置篇 5.7 节的行为佐证中复核)。

media:gc 清理孤儿媒体:删除未挂到任何活跃帖子上的媒体记录。用 tinker 先数一遍孤儿(上一章相册上限实验遗留 2 条):

docker compose exec pixelfed php artisan tinker --execute='echo "total=".\App\Models\Media::count()." orphan=".\App\Models\Media::whereNull("status_id")->count();'

实测回显:

total=10 orphan=2

执行清理:

docker compose exec pixelfed php artisan media:gc

实测回显:

    0 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░]

执行后再次计数(回显仍为 total=10 orphan=2):孤儿数未变化——media:gc 只回收产生超过 2 小时的孤儿媒体,刚产生的孤儿会被保留,给「误删后恢复帖子」留窗口。这与配置篇 5.4 节「第 5 张媒体被静默跳过成为孤儿」的现象闭环:孤儿会在 2 小时后由本命令(或每小时 :05 的计划任务)自动回收。

💡 技术拓展:清理「无主媒体/存储残留」有三条命令可选——

命令清理对象时机
media:gc未挂到活跃帖子的孤儿媒体记录2 小时保留期后(每小时的计划任务)
media:filtercleanup帖子已不存在等异常状态的媒体维护手工排障
storage:maintenanceremcache 临时文件与空目录(存储层残留)每日 04:15 计划任务

本文按「先记录级(media:gc)、再存储级(storage:maintenance)」的顺序执行,media:filtercleanup 留给异常排查场景。

4.6 数据导入(import 命令族)

import:cities 导入城市数据:城市数据支撑发帖时的地点/位置功能。发行包不含数据文件,直接执行会报错(实测回显):

Error: The file storage/app/cities.json is missing. Run `git checkout storage/app/cities.json` to download it.

解决:从 GitHub 对应 tag 下载 cities.json 放入存储目录(实测文件 12977722 字节),再执行导入(命令与《PixelFed 0.15.2 Docker Compose 部署指南》第十一章 FAQ Q8 同源):

curl -fsSL -o /opt/pixelfed/storage/app/cities.json \
  https://raw.githubusercontent.com/pixelfed/pixelfed/v0.15.2/storage/app/cities.json
chown 33:33 /opt/pixelfed/storage/app/cities.json
docker compose exec pixelfed php artisan import:cities

签名中的 [<chunk>] 为分批写入大小(默认 1000)。导入完成后用 db:table 验证数据落位:

docker compose exec pixelfed php artisan db:table places

实测回显(输出节选,实测首尾):

  pixelfed.places ............................................................  
  Columns ................................................................. 13  
  Size .............................................................. 42.16 MB  
  Engine .............................................................. InnoDB  
  Collation ............................................... utf8mb4_unicode_ci  

  Column ................................................................ Type  
  id bigint, autoincrement ............................... bigint(20) unsigned  
  slug varchar, utf8mb4_unicode_ci .............................. varchar(255)  
  name varchar, utf8mb4_unicode_ci .............................. varchar(255)  
  state varchar, nullable, utf8mb4_unicode_ci .............. NULL varchar(255)  
  country varchar, utf8mb4_unicode_ci ........................... varchar(255)  
……(中间为 aliases/lat/long/score/created_at/updated_at/cached_post_count/last_checked_at 各列与 8 个索引定义)……  
  Index ......................................................................  
  places_country_index country ......................................... btree  
  places_slug_country_lat_long_unique slug, country, lat, long  btree, compound, unique  
  primary id .................................................. btree, primary  
docker compose exec pixelfed php artisan tinker --execute='echo \Illuminate\Support\Facades\DB::table("places")->count();'

实测回显:

128769

解读:places 表 42.16 MB、128769 行城市记录(唯一索引对原始数据做了去重),位置功能数据就绪。

import:emojis 导入自定义表情:签名要求必填 <path>(表情 tar.gz 包路径),并有 --prefix/--suffix/--overwrite/--disabled 四个选项。缺参直接执行会报错(实测回显):

  Not enough arguments (missing: "path").  

(提示前后各有一行空白填充,属 Symfony 命令行的标准错误格式。)本环境未制作表情包,仅验证签名与缺参行为;需要自定义表情时,把打好的 tar.gz 放到应用可读路径后传入即可。

4.7 存储与密钥初始化(storage / passport / key / instance 命令族)

这一组命令集中在初始化阶段执行,重复执行的行为各不相同——本节逐一复跑验证,这是升级或迁移环境时最容易踩坑的地方。

storage:link 创建公开存储符号链接(首次执行创建成功;部署指南 4.5 节已实测首次执行),复跑实测:

docker compose exec pixelfed php artisan storage:link

实测回显:

ERROR  The [public/storage] link already exists.  

passport:keys 生成 OAuth 加密密钥,复跑实测:

docker compose exec pixelfed php artisan passport:keys

实测回显:

ERROR  Encryption keys already exist. Use the --force option to overwrite them.  

key:generate 查看应用密钥(--show 只展示不落盘,密钥本身在 .env 的 APP_KEY,见配置篇 5.1 节):

docker compose exec pixelfed php artisan key:generate --show

实测回显:

base64:bm8hWRcRAgQ9LFRyvDgraqvX1J23z2mSht7dKIp3n70=

(每环境生成值不同,不可照抄他人值。)

instance:actor 生成实例 Actor(联邦身份记录,初始化时执行),复跑实测:

docker compose exec pixelfed php artisan instance:actor

实测回显:

Instance actor succesfully generated. You do not need to run this command again.

幂等性对照小结:

命令复跑行为退出码
storage:link报 ERROR「已存在」0
passport:keys报 ERROR「已存在」,提示 --force 覆盖1
instance:actor正常重新生成并提示无需再跑0
media:gc / gc:sessions / story:gc无待处理项时静默完成0

解读:脚本化判断成败不能只看是否打印 ERROR——storage:link 报错但退出码为 0;跨命令统一以退出码为准,且 passport:keys 的 --force 会覆盖密钥(旧令牌全部失效),非排障不要加。

4.8 站点诊断与维护模式(about / app:federation / down / up)

about 一屏总览运行环境:

docker compose exec pixelfed php artisan about

实测回显(全文):


  Environment ................................................................  
  Application Name .................................................. Pixelfed  
  Laravel Version .................................................... 13.38.0  
  PHP Version ......................................................... 8.5.12  
  Composer Version .................................................... 2.10.3  
  Environment ..................................................... production  
  Debug Mode ............................................................. OFF  
  URL ................................................... 192.168.146.128:8135  
  Maintenance Mode ....................................................... OFF  
  Timezone ............................................................... UTC  
  Locale ............................................................... en-US  

  Cache ......................................................................  
  Config .............................................................. CACHED  
  Events .............................................................. CACHED  
  Routes .............................................................. CACHED  
  Views ............................................................... CACHED  

  Drivers ....................................................................  
  Broadcasting ........................................................... log  
  Cache ................................................................ redis  
  Database ............................................................. mysql  
  Logs ......................................................... stack / daily  
  Mail ................................................................... log  
  Queue ................................................................ redis  
  Session ........................................................... database  

  Storage ....................................................................  
  public/storage ...................................................... LINKED  

  Pulse ......................................................................  
  Enabled ................................................................ OFF  
  Version ............................................................. v1.8.1  

  Livewire ...................................................................  
  Livewire ............................................................ v4.4.8  

解读:排障第一入口——Maintenance Mode 行对应 4.8 节 down/up 状态;Cache 节四个 CACHED 对应配置/路由缓存已构建(清缓存后变灰);public/storage LINKED 对应 storage:link 成效。

app:federation 联邦全链路诊断:对配置、实例 Actor、本地端点、HTTP 签名、队列、投递健康、运行环境做体检:

docker compose exec pixelfed php artisan app:federation

实测回显(本环境 ACTIVITY_PUB=false 单实例形态,全文照抄):

================================================================
CONFIG
================================================================
  ✓ APP_ENV is production
  ✗ ActivityPub is disabled  env=false admin setting=false
      ↳ Set ACTIVITY_PUB=true, then run php artisan config:cache.
  ! Inbox (AP_INBOX) is disabled
  ! Outbox (AP_OUTBOX) is disabled
  ! Shared inbox (AP_SHAREDINBOX) is disabled
  ! Remote follow (AP_REMOTE_FOLLOW) is disabled
  ✓ WebFinger enabled
  ✓ NodeInfo enabled
  · Authorized fetch  disabled (env=false)
  · Followers sync (FEP-8fcf)  enabled
  · Delivery tuning  timeout=30s concurrency=10 failure_threshold=5 max_backoff=604800s
  ✗ APP_URL is not https  http://192.168.146.128:8135
      ↳ Actor ids are built from APP_URL and Pixelfed only accepts https ActivityPub URLs.
  ✓ APP_URL host matches APP_DOMAIN  192.168.146.128
  ✓ Cached config is newer than .env
  · Cache store  redis
  ✓ No pending migrations

================================================================
INSTANCE ACTOR
================================================================
  ✓ Instance actor exists  http://192.168.146.128:8135/i/actor
  ✓ Instance actor keypair is valid  2048 bit RSA, public key derives from private key
  ✓ Cached private key matches the database
  ✓ Cached public key matches the database
  · Cached actor document  not cached yet

================================================================
LOCAL ENDPOINTS (outside-in)
================================================================
  ✓ host-meta  points at /.well-known/webfinger
  ✓ WebFinger acct:admin@192.168.146.128  self link is http://192.168.146.128:8135/users/admin
  ✓ NodeInfo discovery  http://192.168.146.128:8135/api/nodeinfo/2.0.json
  ✓ NodeInfo document  pixelfed 0.15.2, protocols: activitypub
  ✓ Instance actor document  id, inbox and publicKeyPem all match
  ✗ Actor @admin as application/activity+json  HTTP 302, expected 200
      ↳ Redirects to http://192.168.146.128:8135/admin. Remote servers do not reliably follow redirects here, APP_URL should be the canonical origin.
  ✗ Actor @admin as application/ld+json  HTTP 302, expected 200
      ↳ Redirects to http://192.168.146.128:8135/admin. Remote servers do not reliably follow redirects here, APP_URL should be the canonical origin.
  ✓ Shared inbox route reaches Laravel  GET /f/inbox returned 405 as expected

================================================================
HTTP SIGNATURES
================================================================
  ✓ All active local profiles have a keypair  2 profiles
  ✓ POST signature round trip as @admin  signed headers: (request-target) host date digest content-type user-agent
  ✓ GET signature round trip as the instance actor  signed headers: (request-target) host date accept

================================================================
QUEUES
================================================================
  · Queue connection  redis (redis driver)
  ✓ Horizon is running  1 master supervisor(s)

+---------+--------+---------+------+-------------------------------------------------+
| Queue   | Worker | Pending | Wait | Carries                                         |
+---------+--------+---------+------+-------------------------------------------------+
| default | yes    | 0       | 0s   | outbound status delivery                        |
| high    | yes    | 0       | 0s   | user inbox activities                           |
| shared  | yes    | 0       | 0s   | shared inbox activities                         |
| follow  | yes    | 0       | 0s   | inbound and outbound follows                    |
| inbox   | yes    | 0       | 0s   | inbound actor deletes                           |
| delete  | yes    | 0       | 0s   | inbound deletes                                 |
| story   | yes    | 0       | 0s   | story deletes                                   |
| feed    | yes    | 0       | 0s   | likes, home feed inserts after ingest           |
| low     | yes    | 0       | 0s   | shares, signing actor discovery, remote avatars |
| move    | yes    | 0       | 0s   | account migration                               |
+---------+--------+---------+------+-------------------------------------------------+
  ✓ No failed federation jobs in the last 24h  0 failed jobs scanned

================================================================
DELIVERY HEALTH
================================================================
  · Known instances  0 total, 0 banned
  ✓ No hosts with delivery failures
  · Banned domain cache  not cached yet
  · Audience of @admin  0 inboxes on 0 hosts, 0 host(s) currently skipped

================================================================
ENVIRONMENT
================================================================
  · PHP  8.5.12 (cli)
  ✓ Required PHP extensions and dns_get_record() are available
  ✗ Own domain does not pass the public IP check from this server  192.168.146.128 -> 192.168.146.128
      ↳ Helpers::validateLocalUrl() fails here, so inbound Follows, replies (inReplyTo) and Undos that reference local URLs are dropped. One private or reserved record (split-horizon DNS, internal resolver, ULA AAAA) is enough. Negative results are cached for 5 minutes.
  ✗ Outbound HTTPS to https://pixelfed.org failed  ConnectionException: cURL error 28: Connection timed out after 5001 milliseconds (see https://curl.se/libcurl/c/libcurl-errors.html) for https://pixelfed.org
      ↳ If every outbound request fails, look at the egress firewall, DNS and the CA bundle (curl.cainfo).

================================================================
SUMMARY
================================================================
  23 ok, 4 warning(s), 6 failure(s), 0 skipped

FAILURES:
  ✗ [config] ActivityPub is disabled
  ✗ [config] APP_URL is not https
  ✗ [endpoints] Actor @admin as application/activity+json
  ✗ [endpoints] Actor @admin as application/ld+json
  ✗ [env] Own domain does not pass the public IP check from this server
  ✗ [env] Outbound HTTPS to https://pixelfed.org failed

WARNINGS:
  ! [config] Inbox (AP_INBOX) is disabled
  ! [config] Outbox (AP_OUTBOX) is disabled
  ! [config] Shared inbox (AP_SHAREDINBOX) is disabled
  ! [config] Remote follow (AP_REMOTE_FOLLOW) is disabled

解读:SUMMARY 的 6 项 failure 全部源于「内网 HTTP + 联邦关闭」的单实例形态——ACTIVITY_PUB=false 与 APP_URL 非 https 是配置选择(配置篇 5.8 节有逐项解读);ENVIRONMENT 两项 ✗ 是纯内网环境的预期表现(私网地址过不了公网解析检查、无公网出站)。QUEUES 节是 Horizon 十个队列的健康快照。开启联邦前跑一次本命令、按 ✗ 逐项清零,是最稳的启用路径。

down / up 维护模式开关(含行为验证):

docker compose exec pixelfed php artisan down
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: 192.168.146.128' http://127.0.0.1:8135/login
docker compose exec pixelfed php artisan up
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: 192.168.146.128' http://127.0.0.1:8135/login

实测回显:

INFO  Application is now in maintenance mode.  
503
INFO  Application is now live.  
200

解读:down 后所有请求 503(升级维护窗口的标准姿势),up 即刻恢复 200。curl 带 Host 头是因为路由按 APP_DOMAIN 域名约束注册,直接以 127.0.0.1 访问会 404(配置篇 5.3 节有该行为的完整实测)。

4.9 垃圾回收(gc / story 命令族)

gc 族与 story:gc 均已进入调度表(见 4.4 节),手工执行用于补跑。三者对待处理项为空时静默完成(无输出),实测退出码均为 0:

docker compose exec pixelfed php artisan gc:sessions; echo "exit=$?"
docker compose exec pixelfed php artisan story:gc; echo "exit=$?"

实测回显:

exit=0
exit=0
命令清理对象调度计划
gc:failedjobs超过 1 个月的失败队列作业每日 03:00
gc:passwordreset超过 24 小时的密码重置令牌每日 09:41
gc:sessions数据库会话(SESSION_DRIVER=database 时)每日 13/23 点
story:gc过期故事每 5 分钟

五、注意事项

  1. 破坏性命令清单:migrate:fresh / migrate:reset / migrate:refresh(删表重迁)、db:wipe(清空全库)、user:delete(删号)、horizon:terminate(停消费器)、queue:flush(清空失败作业)、passport:keys --force(覆盖密钥致旧令牌失效)——生产执行前必须确认备份;日常巡检只读命令(status、list、db:table、horizon:status)可放心使用。
  2. 复跑行为不一致:同是「已存在」类报错,storage:link 退出码为 0、passport:keys 为 1、instance:actor 幂等成功(4.7 节对照表)。脚本里判断成败以退出码为准,不要 grep 关键字。
  3. 交互式命令的自动化:user:admin 的 yes/no 确认、user:checkpassword 的隐藏密码输入都走标准输入,自动化统一用管道(echo yes |、echo 'q1w2e3r4' |),并给 exec 加 -T 关闭伪终端分配。
  4. 清缓存类命令与实例开关的联动:optimize:clear / config:clear 会连同实例配置缓存一起失效,实例级开关(如注册、故事)会回到 .env 取值,修改 .env 后需按「清缓存 + 重建缓存」两步走,完整机制与实测见《PixelFed 0.15.2 配置参数详解》第三章。
  5. 命令执行形态:所有命令经编排内执行形态调用(部署目录 /opt/pixelfed 下 docker compose exec pixelfed php artisan ...),不要在宿主机直接找 php 可执行文件——CLI 与 Web 必须共用同一数据库与 APP_KEY(user:checkpassword 的诊断回显同样如此提示)。

六、常见问题

Q1:horizon:status 显示 stopped 或无输出 Horizon 常驻消费器未运行。先确认编排中 horizon 服务存活(部署指南 4.5 节的服务构成与 4.7 节的验证方式),再用 php artisan horizon:list 查看监督器是否注册;修改队列配置后需 horizon:terminate 让其按新配置重启。

Q2:media:gc 执行后孤儿媒体还在 不是故障:实测确认 media:gc 只回收产生超过 2 小时的孤儿(4.5 节前后计数不变即此因)。等下一个整点 :05 的计划任务或届时手工补跑即可。

Q3:import:cities 报 cities.json is missing 发行包不含城市数据文件,按 4.6 节两步走:从 GitHub v0.15.2 tag 下载 cities.json 放入存储目录并修正属主,再执行导入;导入结果用 db:table places 与行数查询验证(实测 42.16 MB / 128769 行)。

Q4:用户反馈登录不上,如何定位 先用 user:checkpassword <用户名> 做只读诊断(4.1 节实测):密码匹配仍被拒时按回显四条线索排查(重复邮箱、输入误差、APP_KEY 不一致、5 次/60 分钟登录节流);密码不匹配用 user:setpassword 重置后再验。

Q5:app:federation 一片 ✗ 是不是装坏了 对照 SUMMARY 分节看:[config]/[endpoints] 的 ✗ 来自 ACTIVITY_PUB=false 或 APP_URL 非 https(内网单实例的配置选择),[env] 的两项 ✗ 是纯内网环境的预期;只要 INSTANCE ACTOR、HTTP SIGNATURES、QUEUES 三节全 ✓,单实例功能即健康。

Q6:命令应该在哪个目录、什么身份执行 统一在部署目录 /opt/pixelfed 下以编排内执行形态运行(docker compose exec pixelfed php artisan ...),由编排保证工作目录与运行用户;千万不要绕开编排直接以其他身份操作存储目录——属主错乱会导致日志/缓存写入失败(部署指南第四章 FAQ 有该坑实录)。

七、参考链接