PixelFed 0.15.2 配置参数详解

逐项讲清 PixelFed v0.15.2 的 .env 配置体系(APP/实例准入/站点地址与 Cookie/媒体/功能开关/数据库与 Redis/队列与 Horizon/联邦/邮件与对象存储),关键参数均给出修改、生效、验证的实测闭环,开放注册、故事、文案与相册上限四项完成行为级闭环。

PixelFedPixelFed自托管2026/10/27

PixelFed 0.15.2 配置参数详解

目标:逐项讲清 PixelFed v0.15.2 的 .env 配置体系(APP / 实例准入 / 站点地址与 Cookie / 媒体 / 功能开关 / 数据库与 Redis / 队列与 Horizon / 联邦 / 邮件与对象存储),每一组关键参数都给出「修改 → 生效 → 验证」的实测闭环。已在 Ubuntu 22.04 服务器(IP 192.168.146.128,端口 8135)实测通过,其中开放注册、故事开关、文案上限、相册上限四个参数完成了完整的行为级闭环验证。

一、环境信息

项目实测值
操作系统Ubuntu 22.04(x86_64)
PixelFedv0.15.2(官方编排形态部署)
数据库MariaDB 11.8
缓存/队列Redis 8
配置文件/opt/pixelfed/.env(基于官方 .env.example 88 行)
访问地址http://192.168.146.128:8135
演示账号admin / q1w2e3r4(管理员)

本文命令均在部署目录 /opt/pixelfed 下执行,各 php artisan 命令一律通过编排内执行形态调用(同《PixelFed 0.15.2 Docker Compose 部署指南》4.6 节的方式)。

二、前置条件

  1. 已完成 v0.15.2 部署并迁移通过(php artisan migrate:status 计 268 个 Ran);
  2. 服务全部 healthy(5 个服务 Up,健康检查通过);
  3. 已有管理员账号可登录(验证行为级闭环需要会话);
  4. 理解「配置缓存」双层机制(见第三章)——这是本文绝大多数「改了不生效」问题的根源。

三、参数查看与修改方式

3.1 查看参数当前值

两种实测方式:config:show(看 Laravel 运行时配置)与 tinker 的 config_cache()(看 Pixelfed 实例配置缓存层)。

# 方式一:config:show 查看像素配置组(pixelfed 配置键)
docker compose exec pixelfed php artisan config:show pixelfed

实测回显(输出节选):

  max_photo_size ....................................................... 15000
  max_caption_length ..................................................... 500
  max_album_length ......................................................... 4
  image_quality ........................................................... 80
# 方式二:tinker 查看实例配置缓存层取值
docker compose exec pixelfed php artisan tinker --execute='echo var_export(config_cache("pixelfed.max_album_length"),true);'

实测回显:

4

3.2 修改参数的标准三步

# 第 1 步:编辑 /opt/pixelfed/.env(本文以 sed 为例,手改亦可)
sed -i 's/MAX_ALBUM_LENGTH="4"/MAX_ALBUM_LENGTH="6"/' /opt/pixelfed/.env
# 第 2 步:重建服务使新环境变量进入运行时(restart 不重读 .env,实测无效)
cd /opt/pixelfed && docker compose up -d
# 第 3 步:验证生效
docker compose exec pixelfed php artisan config:show pixelfed | grep max_album_length

⚠️ 注意:docker compose restart 只重启不重读 .env,改动必须用 up -d 重建(实测踩坑:restart 后 php -r 'echo getenv(...)' 仍是旧值)。

3.3 「配置缓存」机制(改参数不生效的第一嫌疑)

Pixelfed 在 Laravel 自身配置缓存之外还有实例配置缓存(ENABLE_CONFIG_CACHE=true 时启用):启动时把一批实例级开关写入数据库 config_caches 表并同步到 Redis(键名形如 config_cache:_v0-key:pixelfed.open_registration,12 小时 TTL),运行期 config_cache() 优先读缓存,未命中才回源 config()。因此对实例级开关,仅改 .env 重建可能仍读旧值,需要「删缓存行 + 删 Redis 键 + 重建缓存」三连:

# 清除单键(以 pixelfed.open_registration 为例)
docker compose exec pixelfed php artisan tinker --execute='$r=\App\Models\ConfigCache::where("k","pixelfed.open_registration")->first(); if($r)$r->delete(); \Illuminate\Support\Facades\Cache::forget("config_cache:_v0-key:pixelfed.open_registration");'
# 重建配置/路由/视图缓存
docker compose exec pixelfed sh -c 'php artisan optimize:clear && php artisan optimize'

该机制在本文 5.2(开放注册)与 5.5(故事开关)两处有完整行为级闭环实测。

四、参数总览

按官方 .env.example 的分组顺序,v0.15.2 全量变量分组如下(默认值取自官方 .env.example,实测值取自本环境):

分组变量(默认值 → 实测值)生效层级
APP 基础APP_NAME="Pixelfed"、APP_ENV="production"、APP_KEY(必填生成)、APP_DEBUG="false"、APP_LOCALE="en-US"运行时
实例准入OPEN_REGISTRATION="false"、ENFORCE_EMAIL_VERIFICATION="false"、PF_MAX_USERS="1000"、PF_MIN_REGISTRATION_AGE="16"、OAUTH_ENABLED="true"、OAUTH_PAT_ENABLED="false"实例缓存
站点功能ENABLE_CONFIG_CACHE="true"、INSTANCE_DISCOVER_PUBLIC="true"、STORIES_ENABLED(未含于样例,默认 false → 实测 true)实例缓存
媒体IMAGE_DRIVER=vips、PF_OPTIMIZE_IMAGES="true"、IMAGE_QUALITY="80"、MAX_PHOTO_SIZE="15000"、MAX_CAPTION_LENGTH="500"、MAX_ALBUM_LENGTH="4"运行时
站点地址APP_URL、APP_DOMAIN、ADMIN_DOMAIN、SESSION_DOMAIN=null、TRUST_PROXIES="*"、FORCE_HTTPS_URLS(默认 true → 实测 false)、SESSION_SECURE_COOKIE(默认 true → 实测 false)运行时
数据库DB_CONNECTION="mysql"、DB_HOST="db"、DB_PORT="3306"、DB_DATABASE/DB_USERNAME/DB_PASSWORD(自定)、DB_ROOT_PASSWORD(编排健康检查引用)运行时
RedisREDIS_CLIENT="predis"、REDIS_SCHEME="tcp"、REDIS_HOST="redis"、REDIS_PASSWORD="null"、REDIS_PORT="6379"运行时
会话/队列SESSION_DRIVER="database"、CACHE_STORE="redis"、QUEUE_DRIVER="redis"、BROADCAST_DRIVER="log"、LOG_CHANNEL="stack"、HORIZON_PREFIX="horizon-"运行时
联邦ACTIVITY_PUB="false"、AP_REMOTE_FOLLOW="false"、AP_INBOX="false"、AP_OUTBOX="false"、AP_SHAREDINBOX="false"运行时
实验EXP_EMC="true"(媒体缓存扩展)实例缓存
邮件MAIL_DRIVER=log、MAIL_HOST/PORT/USERNAME/PASSWORD/ENCRYPTION、MAIL_FROM_ADDRESS="pixelfed@example.com"、MAIL_FROM_NAME="Pixelfed"、MAIL_AUTO_TLS=true运行时
对象存储PF_ENABLE_CLOUD=false、FILESYSTEM_CLOUD=s3、AWS_*(注释态)运行时

解读:标注「实例缓存」的分组受 3.3 节机制固化,改动要按三连步骤处理;「运行时」分组改 .env 重建即生效。

五、核心参数分类详解

5.1 APP 基础参数

变量说明
APP_KEY应用级加密密钥(会话/加密)。生成:docker compose exec pixelfed php artisan key:generate --show,实测输出 base64:bm8hWRcRAgQ9LFRyvDgraqvX1J23z2mSht7dKIp3n70=(每环境不同,不可照抄他人值)。更换后所有已登录会话失效
APP_ENVproduction / local。production 下日志精简、报错不外显
APP_DEBUGtrue 时错误页带堆栈,仅排障临时开启
APP_LOCALE界面语言,en-US 默认

验证方式:

docker compose exec pixelfed php artisan config:show app | grep -E "env|debug"

实测回显(输出节选):

  env ................................................................ production
  debug ..................................................................... false

5.2 实例准入参数(含开放注册全闭环实测)

变量说明实测默认
OPEN_REGISTRATION开放注册总开关,控制 /register 路由是否注册false
ENFORCE_EMAIL_VERIFICATION注册后强制邮箱验证false
PF_MAX_USERS实例用户总数上限1000
PF_MIN_REGISTRATION_AGE注册最小年龄限制16
OAUTH_ENABLEDOAuth 2.0(官方移动端/第三方客户端登录必需)true
OAUTH_PAT_ENABLED个人访问令牌(PAT)自助签发入口false

OPEN_REGISTRATION 实测闭环(三段完整行为验证):

  1. false 时 /register 直接 404(路由未注册):
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.146.128:8135/register

实测回显:

404
  1. 改 .env 为 true 并按 3.3 三连清缓存后,路由注册成功:
curl -s http://192.168.146.128:8135/register | grep -oE '<title>[^<]*</title>'

实测回显:

<title>注册 · Pixelfed</title>
  1. 还原 false 并清缓存,恢复 404(略去回显,同第 1 步)。

⚠️ 注意:/register 路由是启动时按开关条件注册的——只清配置缓存不够,还必须 php artisan optimize:clear && php artisan optimize 重建路由缓存,这是实测得出的完整生效条件。

变量说明实测结论
APP_URL对外完整地址(含协议/端口)必须与实际访问地址一致
APP_DOMAIN / ADMIN_DOMAIN域名约束(不含协议)路由按它注册,不一致整站 404
FORCE_HTTPS_URLS强制生成 https 链接默认 true;HTTP 部署必须 false
SESSION_SECURE_COOKIE会话 Cookie secure 标志默认 true;HTTP 部署必须 false
TRUST_PROXIES反向代理场景的可信代理段"*" 表示全信任

APP_DOMAIN 实测闭环:配置 APP_DOMAIN="192.168.146.128" 时,用 127.0.0.1 访问登录页返回 404,而 API 正常——

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8135/login
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.146.128:8135/login

实测回显:

404
200

原因:路由按 APP_DOMAIN 域名约束注册,Host 不匹配即 404。生产改域名时三处(APP_URL/APP_DOMAIN/ADMIN_DOMAIN)必须同步改。

FORCE_HTTPS_URLS 实测闭环:默认 true 时登录表单 action 被强制生成为 https:

<form method="POST" action="https://192.168.146.128:8135/login">

置 false 重建后:

<form method="POST" action="http://192.168.146.128:8135/login">

SESSION_SECURE_COOKIE 实测闭环:默认 true 时登录响应头带 secure(HTTP 下浏览器丢弃 Cookie,登录永远失败):

set-cookie: pxfs=...; path=/; httponly; samesite=lax; secure

置 false 重建后登录成功(302 → /i/web)。

5.4 媒体处理参数

变量默认说明
IMAGE_DRIVERvips图片处理驱动(vips/gd/imagick)
PF_OPTIMIZE_IMAGEStrue上传后由队列异步优化(缩略/压缩),Horizon 停机会导致缩略图不生成
IMAGE_QUALITY80JPEG 压缩质量(1-100)
MAX_PHOTO_SIZE15000单图上限(KB,即 15MB)
MAX_CAPTION_LENGTH500文案上限,按 Unicode 字符计数(实测 600 字符被拒、520 字符可发)
MAX_ALBUM_LENGTH4单帖(相册)图片上限,可调至 10

MAX_CAPTION_LENGTH 实测闭环(520 字符通过 → 600 字符 422)。实测以 admin 会话复放发布接口:登录后的会话 Cookie 存入 cookies.txt、CSRF 令牌存入变量 XSRF(取值方法:登录响应头 X-XSRF-TOKEN,或浏览器开发者工具同名项):

curl -s -b cookies.txt -H "X-XSRF-TOKEN: $XSRF" -H 'Content-Type: application/json' \
  -X POST http://192.168.146.128:8135/api/compose/v0/publish \
  -d '{"caption":"(600 个『长』字)","media":[{"id":5,"cursor":0}],"visibility":"public"}'

实测回显:

{"message":"The caption field must not be greater than 500 characters.","errors":{"caption":["The caption field must not be greater than 500 characters."]}}

(HTTP 状态 422;验证时可先发 520 字符确认 200,再发 600 字符确认 422,两段本环境均实测。)

MAX_ALBUM_LENGTH 实测闭环(默认 4,一次提交 5 张只挂 4 张):一次 publish 请求携带 5 个 media id,实测返回 200 后核对:

docker compose exec pixelfed php artisan tinker --execute='$s=\App\Models\Status::where("caption","like","%相册上限实测%")->first(); echo "status_id=".$s->id." media_count=".\App\Models\Media::where("status_id",$s->id)->count(); echo " orphan=".join(",", \App\Models\Media::whereNull("status_id")->pluck("id")->all());'

实测回显:

status_id=1020378795510095814 media_count=4 orphan=5,10

第 5 张媒体被静默跳过并成为孤儿记录,维护窗口内可用 php artisan media:gc 清理(实测该命令仅回收超过 2 小时的孤儿媒体)。

IMAGE_DRIVER 验证:

docker compose exec pixelfed php artisan config:show pixelfed | grep -E "image_driver|image_quality"

实测回显:

  image_driver ............................................................ vips
  image_quality ........................................................... 80

5.5 站点功能开关(含故事开关闭环实测)

变量默认说明
STORIES_ENABLEDfalse故事(Stories)功能总开关,关闭时相关路由不注册
ENABLE_CONFIG_CACHEtrue实例配置缓存(3.3 节机制)
INSTANCE_DISCOVER_PUBLICfalse发现页公开性
EXP_EMCfalse实验性媒体缓存(实测开启)

STORIES_ENABLED 实测闭环:

  1. 默认 false 时上传故事直接被拒,实测响应体为空错误对象:
{"error":""}
  1. 改 .env 为 true、按 3.3 三连清缓存(对应键 instance.stories.enabled 与 pixelfed.stories.enabled)后,重新上传故事返回:
{"code":200,"msg":"Successfully added","media_id":"1020379318853533699","media_type":"photo"}
  1. 随后裁剪与发布两个接口均返回 {"code":200,"msg":"Successfully published"},故事出现在个人主页故事栏(GET /api/web/stories/v1/recent 返回含该故事的列表)。

💡 技术拓展:实例级开关的存储层级有三种形态——

层级介质生效方式
运行时 config.env → Laravel 配置重建服务即生效
实例配置缓存config_caches 表 + Redis(12h TTL)需清缓存行与键
管理后台动态设置config_caches 表(后台写入)后台保存即时生效

同一开关可能同时出现在多层(如 OPEN_REGISTRATION 也可在管理后台切换),排查「不生效」时按「后台动态设置 → 实例缓存 → .env」顺序核对。本文方案统一走 .env + 三连清理。

5.6 数据库与 Redis 参数

docker compose exec pixelfed php artisan config:show database | grep -A2 "mysql ⇁"

实测回显(输出节选):

  connections ⇁ mysql ⇁ host .............................................. db
  connections ⇁ mysql ⇁ database .................................... pixelfed
变量实测取值说明
DB_CONNECTIONmysql驱动名(MariaDB 亦用 mysql 驱动);切换 PostgreSQL 改 pgsql
DB_HOST / DB_PORTdb / 3306编排内服务名
DB_DATABASE / DB_USERNAME / DB_PASSWORDpixelfed / pixelfed / q1w2e3r4业务库凭据
DB_ROOT_PASSWORDq1w2e3r4编排健康检查引用,缺失会导致数据库初始化失败
REDIS_CLIENT / REDIS_SCHEME / REDIS_HOST / REDIS_PORTpredis / tcp / redis / 6379编排内服务名
REDIS_PASSWORDnull编排未设密码,字面量 null

MySQL 9 不可用的实测结论(迁移中断):

ERROR 3763 (HY000) at line 1: Expression of generated column 'key_hash' contains a disallowed function: `md5`.

同一语句 MariaDB 11.8 实测建表成功。因此 DB 连接层面选 MariaDB 11.x;切换数据库后需重建服务并重新迁移(数据不自动迁移,跨库迁移属另一话题)。

5.7 会话、缓存与队列参数

变量实测取值说明
SESSION_DRIVERdatabase会话存数据库 sessions 表(重装应用不丢登录态);可改 redis
CACHE_STOREredis应用缓存
QUEUE_DRIVERredis异步队列,Horizon 消费
BROADCAST_DRIVERlog广播(Websocket 未启用时 log)
LOG_CHANNELstack日志通道
HORIZON_PREFIXhorizon-Horizon 的 Redis 键前缀(多实例共用 Redis 时区分)

队列验证(Horizon 工作器与队列通路):

docker compose exec pixelfed php artisan horizon:status

实测回显:

INFO  Horizon is running.
docker compose exec pixelfed php artisan queue:failed

实测回显:

INFO  No failed queue jobs found.

行为佐证:上传图片后 Media 表 processed_at 非空、缩略图生成(队列消费完成的标志,实测 3 张媒体全部 processed)。

5.8 联邦参数(ActivityPub)

变量默认说明
ACTIVITY_PUBfalse联邦总开关
AP_REMOTE_FOLLOWfalse允许远程账号关注本站用户
AP_INBOX / AP_OUTBOX / AP_SHAREDINBOXfalse收件箱/发件箱/共享收件箱端点开关
INSTANCE_DISCOVER_PUBLICfalse实例元数据公开
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

要点(均来自诊断器自身输出):CONFIG 节明确提示 ✗ APP_URL is not https,并注明 Actor id 由 APP_URL 构建、Pixelfed 只接受 https 的 ActivityPub URL;实例 Actor 由 instance:actor 命令创建(重复执行幂等,实测回显 Instance actor succesfully generated. You do not need to run this command again.);LOCAL ENDPOINTS 节两项 ✗(Actor JSON 探测被 302 重定向到登录页)是 APP_URL 非 https 域名的伴生现象;ENVIRONMENT 节两项 ✗(内网 IP 未通过公网解析检查、出站 HTTPS 探测 5 秒超时)是纯内网环境的预期表现。本环境为纯内网 HTTP 部署,如实保持 ACTIVITY_PUB=false 的单实例本地验证形态,联邦互通需公网 HTTPS 域名后另行启用。

六、生产配置模板

适用场景:2 核 4GB 内存、NVMe SSD 100GB、50–200 用户社区、本地磁盘存储。在官方 .env.example 基础上修改以下关键项(其余保持默认):

# ── 基础 ──
APP_NAME="社区名称"
APP_ENV="production"
APP_DEBUG="false"
APP_LOCALE="zh-CN"                        # 界面语言
APP_KEY=${PIXELFED_APP_KEY}               # 由 php artisan key:generate --show 生成后注入(见 5.1 节实测输出)

# ── 地址(公网域名 + 反代 TLS 场景)──
APP_URL="https://pixelfed.example.com"
APP_DOMAIN="pixelfed.example.com"
ADMIN_DOMAIN="pixelfed.example.com"
TRUST_PROXIES="*"                         # 前置 Nginx/Caddy 时保留
FORCE_HTTPS_URLS="true"                   # 有 TLS 时保持默认
SESSION_SECURE_COOKIE="true"              # 有 TLS 时保持默认

# ── 准入治理 ──
OPEN_REGISTRATION="false"                 # 人工/邀请制
ENFORCE_EMAIL_VERIFICATION="true"         # 配合真实 SMTP
PF_MAX_USERS="200"
OAUTH_ENABLED="true"

# ── 媒体 ──
IMAGE_DRIVER=vips
PF_OPTIMIZE_IMAGES="true"
IMAGE_QUALITY="85"
MAX_PHOTO_SIZE="15000"
MAX_CAPTION_LENGTH="1000"
MAX_ALBUM_LENGTH="6"
STORIES_ENABLED="true"

# ── 数据层 ──
DB_CONNECTION="mysql"
DB_HOST="db"
DB_DATABASE="pixelfed"
DB_USERNAME="pixelfed"
DB_PASSWORD="q1w2e3r4"                    # 演示口令,生产环境务必更换
DB_ROOT_PASSWORD="q1w2e3r4"               # 编排健康检查引用,生产环境务必更换
REDIS_HOST="redis"

# ── 会话/队列 ──
SESSION_DRIVER="database"
CACHE_STORE="redis"
QUEUE_DRIVER="redis"

# ── 联邦(公网 HTTPS 就绪后再开)──
ACTIVITY_PUB="true"
AP_REMOTE_FOLLOW="true"
AP_INBOX="true"
AP_OUTBOX="true"
AP_SHAREDINBOX="true"

# ── 邮件(真实 SMTP)──
MAIL_DRIVER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=${SMTP_USERNAME}            # 由邮箱服务商获取后注入
MAIL_PASSWORD=${SMTP_PASSWORD}
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="pixelfed@example.com"
MAIL_FROM_NAME="Pixelfed"

⚠️ 上述模板中 ${PIXELFED_APP_KEY}、${SMTP_USERNAME}、${SMTP_PASSWORD} 为环境级真实密钥,禁止照抄示例:APP_KEY 用 php artisan key:generate --show 生成(5.1 节有实测输出),SMTP 凭据由邮箱服务商控制台获取后替换;数据库口令沿演示口径,生产环境必须更换。媒体量大(TB 级)时叠加 S3 组:PF_ENABLE_CLOUD=true + FILESYSTEM_CLOUD=s3 + AWS_* 七项。

七、常见问题

Q1:改了 .env 重建后行为还是旧值 按「后台动态设置 → 实例配置缓存 → .env」顺序排查:先确认管理后台没有保存过同义开关;再按 3.3 三连清实例缓存键与 config_caches 行;最后确认用 up -d 而非 restart 重建。STORIES_ENABLED 与 OPEN_REGISTRATION 两个开关本环境均复现过此链路并给出完整闭环(5.5/5.2)。

Q2:内网 HTTP 部署登录不上、表单跳 https FORCE_HTTPS_URLS 与 SESSION_SECURE_COOKIE 两个默认值均为 https 场景设计,HTTP 部署必须双双置 false(5.3 有表单 action 与响应头两级实测证据)。

Q3:文案明明没超 500 却被拒(或超了却没拒) MAX_CAPTION_LENGTH 按 Unicode 字符计数:520 个汉字实测可发,600 个汉字实测 422。若给中文社区放宽限制,直接调大该值即可。

Q4:上传成功但缩略图一直不生成 PF_OPTIMIZE_IMAGES=true 时优化在 Horizon 队列执行,先查 php artisan horizon:status;确认 Horizon 服务存活后,重试 php artisan media:optimize 补跑,实测输出 Queued 0 media candidates.(0 表示当前无待优化积压)。

Q5:想切 PostgreSQL DB_CONNECTION=pgsql + 对应 DB_HOST/PORT/库名,重建后重新迁移(Pulse 迁移在 PG 下用 md5("key")::uuid 表达式,官方已适配);数据不自动跨库,需另行导出导入。

八、参考链接