返回列表 发布新帖

[源码] Pocketbase-GO语言高并发单文件api数据库

410 3
阿白 发表于 2026-1-4 12:51:49 | 查看全部 阅读模式 来自:Error

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
<p><img src="data/attachment/forum/202601/04/124813e3zq9f9bjlfbo83v.webp" alt="QQ20260104-124324.webp" title="QQ20260104-124324.webp" /></p>
+ }$ c7 N. x6 b5 A5 R& c<h1>PocketBase 基于 Debian 12 的详细使用指南</h1>6 M) [9 g* A: k' ~# \. f0 p. ]
<h2>一、核心需求确认</h2>
9 |) W$ W2 X# n( n* H# q7 U  g<p>你需要一份面向 Debian 12 系统的 PocketBase 完整操作手册,涵盖从环境准备、安装部署到日常运维的全流程,并以 Markdown 格式整理,方便查阅和使用。</p>
9 ^  t" |# X; S4 N) o. s<h2>二、PocketBase 详细操作指南</h2>5 u) V. k# }3 v; a) S+ Q
<h3>1. 什么是 PocketBase</h3>) Q, ?% ]4 b1 C4 ]5 d9 @
<p>PocketBase 是一个开源的、轻量级的后端即服务(BaaS),集成了实时数据库、认证系统、文件存储和 REST API,单二进制文件运行,无需额外依赖,非常适合小型项目、原型开发或个人项目。</p>
. o+ [/ ~4 v! z1 `% j/ z$ b<h3>2. 环境准备(Debian 12)</h3>& t+ ^/ E8 k0 m8 q
<h4>2.1 系统基础检查与更新</h4>
2 @( S1 e' U0 K5 V( f+ h<p>首先确保 Debian 12 系统为最新状态,执行以下命令:</p>! N3 w6 S8 b. R% D: K- i0 e1 `
<pre><code class="language-bash"># 更新软件包索引
) F6 T5 W2 Q  q' d2 R7 ]3 Hsudo apt update -y8 ?: E; f7 \) ?

& S- L, z3 l) ?0 x! }3 ]# }# 升级已安装的软件包% ?6 e" u; D9 b2 X+ _
sudo apt upgrade -y. X, P6 Z4 n- ~

; N7 @4 v1 I, H! L( b2 D# 安装必要的基础工具(curl、unzip、wget)
9 P/ K  Y, a1 X, H- gsudo apt install curl unzip wget -y9 j  @1 f4 W, m/ L, Y& z9 x

* v# _4 f# H5 \2 a3 ^# {' G# 检查系统架构(PocketBase 需匹配架构下载)
1 V3 k# R# X1 j5 _' luname -m
" Z8 L& n- Y7 l# 常见输出:x86_64(amd64)、aarch64(arm64)
' V, @9 S# T$ X</code></pre>
6 {: i+ [0 z! `! ?<h4>2.2 防火墙配置(可选但推荐)</h4>9 ?' N, z" I& }" s5 H+ i* b
<p>PocketBase 默认使用 8090 端口,需开放该端口:</p>$ z9 \) \, G2 E" `3 T. D
<pre><code class="language-bash"># 查看防火墙状态1 N" T1 M6 z0 e0 {9 l2 c% L
sudo ufw status
9 B+ q+ O% v7 Z' M) ~. U# v# W; q$ k0 P3 I3 M9 r
# 若未启用,先启用防火墙& J4 Z( D1 ?* F0 F1 N6 X; T. W
sudo ufw enable; [/ ~3 x$ ]# r
- l, x0 M8 c. f& q6 J) @; W
# 开放 8090 端口  b  @" P+ l& P% x. M* K
sudo ufw allow 8090/tcp1 }) t" y9 c8 E* T6 w
$ W( \3 V* b) k' k7 H
# 重载防火墙规则& l! H5 q, F( V, U( e2 j' r) n
sudo ufw reload3 O0 v$ L8 x, ?% c
</code></pre>
! F9 P; `+ N% i<h3>3. PocketBase 安装</h3>
' ]- |- U$ |& H! L: Z( u! |4 Q<h4>3.1 下载 PocketBase 二进制文件</h4>- V8 j3 \9 K- d: d6 {0 q
<p>根据系统架构下载对应版本(以最新稳定版为例):</p>
! I7 l4 l, C1 f3 y0 M6 c<pre><code class="language-bash"># 创建 PocketBase 工作目录(推荐)
2 \2 }/ P2 `& n  a* N7 L$ ^/ ^mkdir -p /opt/pocketbase
. d( w; _7 q2 w6 K- [cd /opt/pocketbase
( X! L; V6 M) j- G& H2 o
5 _/ y! g( o( [* A5 g3 X# 下载 amd64 架构版本(Debian 12 服务器主流架构)
' e+ r* w. G2 G/ z" f1 x3 twget https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_linux_amd64.zip
1 j" y) ^) v8 {8 r
5 X3 H7 {1 O, ?2 o# 若为 arm64 架构,替换为:9 Y$ q3 x0 ^6 ]: ^) f7 ]% f
# wget https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_linux_arm64.zip
8 S7 x7 s6 p( {
: l) k4 Q* s' I6 @& Z# 解压文件
- N* ?$ [/ v. lunzip pocketbase_linux_*.zip
& l8 c5 Q$ e' ^2 {$ L! e1 h
; `7 z* c/ w" c. v9 q8 a# 删除压缩包
" u& e% R9 z( C$ w$ Zrm pocketbase_linux_*.zip
% c' Q$ V) [8 V* I6 g  S+ ?) E+ ~. E% F
# 添加执行权限
8 S$ G+ ~6 D( t  g- zchmod +x pocketbase
* |5 [) R7 i- r" z' c
2 n4 p# k; F; L  C# f, h# 验证安装(查看版本)' G$ W4 d' K3 V; G$ i
./pocketbase version
; j3 N$ B) w# e+ F* n2 }( j</code></pre>& e/ Z$ x$ X+ ?: ^# A- P
<h4>3.2 测试运行</h4>
7 g" d" g. C7 G<pre><code class="language-bash"># 首次运行 PocketBase
  y' l% V/ v) i' L5 u) r( Z, W( r0 Z./pocketbase serve
" z9 ?) @* P5 ?
  M& Q( F; L/ u8 l# 运行成功后,终端会输出:
! V: s- |. m! N7 C& K# &gt; Server started at http://0.0.0.0:8090
( F& I, _5 Q' g7 y$ n4 O# G5 ?# &gt; REST API: http://0.0.0.0:8090/api/
5 ?  R+ l9 y5 F: V2 \% v# &gt; Admin UI: http://0.0.0.0:8090/_/
: b* M2 e: G5 R% C# K. H. o8 O</code></pre>
1 B4 W* z: F: ?/ d" b<p>此时可通过 <code>http://你的服务器IP:8090/_/</code> 访问管理后台,首次访问会要求创建管理员账号(用户名/密码)。</p>
% v/ e- H3 O' Q6 d' O$ \<h3>4. PocketBase 基础使用</h3>
: X) E( a( `( ]5 Y6 F<h4>4.1 管理员后台操作</h4>
" _/ M3 W" }, E<ol>* [' l' T" W! p5 D; y
<li>访问 <code>http://服务器IP:8090/_/</code>,输入首次创建的管理员账号登录;</li>0 n3 o" j( A2 {: k
<li><strong>创建数据集合(Collections)</strong>:1 E$ a, v9 g9 _; ^# P' ]
<ul>
2 x7 F4 E5 f# h7 w<li>点击左侧「Collections」→「New collection」;</li>: G- _2 Z) y; n$ @
<li>填写集合名称(如 <code>users</code>)、类型(Base model);</li>
. F7 ^/ @$ G% L; x) ?4 p! u* h<li>添加字段(如 <code>username</code>(Text)、<code>email</code>(Email)、<code>age</code>(Number));</li>- s  f( N$ v3 A
<li>保存后即可通过 API 操作该集合数据。</li>2 h1 I3 ]1 y" Z& f
</ul>2 @& q' V1 C1 @4 N0 x
</li>
- ~2 e  ?8 m  y6 w2 V  M<li><strong>权限配置</strong>:可针对集合设置「Create/Read/Update/Delete」权限(如开放匿名只读、仅管理员可写等)。</li>
9 j$ ?, h, Y% [5 g% J</ol>
$ f# G4 i/ ~2 l, S<h4>4.2 基础 API 使用</h4>* c# t8 r3 h& Z4 D
<p>以 <code>users</code> 集合为例,通过 curl 测试 API:</p>1 x* E' k' j2 _0 _& e9 l
<pre><code class="language-bash"># 1. 创建一条用户数据(需管理员认证,先获取 token): T8 U7 W! t* j! M7 D+ y% p
# 获取管理员 token
1 z) _/ P+ R! ?  ?6 R! b( BADMIN_TOKEN=$(curl -X POST http://服务器IP:8090/api/admins/auth-with-password \6 a0 S7 U6 |& c7 b
  -H &quot;Content-Type: application/json&quot; \) y/ s. ?5 {# R# {
  -d '{&quot;identity&quot;:&quot;你的管理员邮箱&quot;,&quot;password&quot;:&quot;你的管理员密码&quot;}' | jq -r '.token')9 g8 C0 ]) c4 X8 z4 i: z3 ^! N

# a3 R! Y2 x6 c  D5 P7 G. R# 创建用户: w7 A' d! H; y. U' i3 P& F" P% Q1 M
curl -X POST http://服务器IP:8090/api/collections/users/records \' _% M. y- N1 S  m+ B5 M& I
  -H &quot;Content-Type: application/json&quot; \
/ Q# L6 ^* `" R" _  H% R+ ?/ l- q/ T  -H &quot;Authorization: Admin $ADMIN_TOKEN&quot; \
4 B! u+ A6 Z9 v  }: d* T  -d '{&quot;username&quot;:&quot;testuser&quot;,&quot;email&quot;:&quot;test@example.com&quot;,&quot;age&quot;:25}'
3 P5 [/ v- p  d  d
; d$ C( P8 s3 r& v# 2. 查询所有用户数据(匿名访问,需先开放 users 集合的 Read 权限)6 G  r# D1 r+ X2 E+ o; o9 h9 k
curl http://服务器IP:8090/api/collections/users/records
7 p3 }+ ~( }7 \, |</code></pre>7 B# [5 s/ I9 X
<h3>5. 进阶配置(生产环境必备)</h3>9 n6 z- X: t# P5 u" G
<h4>5.1 将 PocketBase 配置为系统服务(开机自启)</h4>9 x1 ]* ^& S+ s3 m
<p>创建 systemd 服务文件,确保 PocketBase 后台运行且开机自启:</p>' G% b, z- W& \( @. t
<pre><code class="language-bash"># 创建服务文件& q' `6 Z" [& w8 m
sudo nano /etc/systemd/system/pocketbase.service' r$ r$ N4 x, R. k7 d. ^8 u+ e0 f  }
</code></pre>
7 K6 ^$ z4 ^# u5 H8 o<p>粘贴以下内容(修改 <code>User</code> 和 <code>WorkingDirectory</code> 为实际路径):</p>' a, p/ t& z2 e, _; J/ L3 {" G
<pre><code class="language-ini">[Unit]
* Y% q5 v% L' ~" _2 bDescription=PocketBase Service' i, n% v0 o8 r+ H6 C( w
After=network.target# F* l- e  _  X/ S0 ~' h

7 e* m3 \$ o" w3 ?1 z' o3 Y[Service]# O+ O/ j! \- D' E, L4 ]
Type=simple1 S1 Z5 s1 ~7 S; N' v8 z" v' T
User=root  # 推荐使用非 root 用户,如创建 pocketbase 用户; }) r2 z+ Y, f. r% b, E: V1 f
WorkingDirectory=/opt/pocketbase# m; x' Z" k, m% _% u( c7 Y
ExecStart=/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090* U) f' T& \3 y3 T# G- R' E/ o* D8 Z
Restart=always# o' x- e( d2 r% C) M) A/ S
RestartSec=5
+ b7 t* V0 }# D: C$ X! ZStandardOutput=journal+console
- V2 m: E4 Y2 y' XStandardError=journal+console
3 H, d" `- @, ?
1 m( \& D0 d7 f8 U[Install]
% A& M- U( L, \0 cWantedBy=multi-user.target
0 D: H5 q# ]8 Y7 D1 r: J: _& [) H</code></pre>) }  }% ?4 P/ C9 ]
<p>保存后执行以下命令启用服务:</p>
0 }1 I% @2 D6 w% ^<pre><code class="language-bash"># 重新加载 systemd 配置7 z" v0 @& ~! s
sudo systemctl daemon-reload9 i0 g1 J" N! S8 e6 J
  \: M5 u( ~: v9 w9 J
# 启动 PocketBase 服务% w- [: z0 X& S1 G# K
sudo systemctl start pocketbase
6 o/ z) ]1 B/ |7 E6 p3 D# Q) Q' j* j% L" D
# 设置开机自启3 n8 [! p" c# |9 c8 v8 z0 T# V
sudo systemctl enable pocketbase4 d% L; x+ j( T. E" H' v( q
# N! C( ?7 o) L' {* r5 X/ X
# 查看服务状态; Z# y. a  z3 E2 j
sudo systemctl status pocketbase
( O" f4 V  A* p! D% B</code></pre>
! P- t( I% M$ Q& t, |: @) S<h4>5.2 配置 HTTPS(推荐)</h4>6 L6 N! h- {8 ?0 A$ U: A5 y
<p>PocketBase 本身不直接支持 HTTPS,需通过 Nginx 反向代理实现:</p>
9 c' A0 H) h4 @. _" F$ }<ol>
% w3 D* s) e" m! x  i3 j<li>安装 Nginx:& w' v0 w% f& O1 W7 H& c
<pre><code class="language-bash">sudo apt install nginx -y% R0 c1 L6 e! [( Z
</code></pre>
6 Y7 ^+ U' K2 n  X: _! z</li>* X. T) B" `5 t* p( B% [. V
<li>创建 Nginx 配置文件:
: F+ F+ B# T* i<pre><code class="language-bash">sudo nano /etc/nginx/sites-available/pocketbase( _, b9 T) I8 U( ]
</code></pre>9 S. t3 ~+ p1 E* ~' k1 @4 m
</li>4 P# Z* m7 S! D. d- {  c# ?3 T
<li>粘贴以下配置(替换 <code>your-domain.com</code> 为你的域名):; }; c% T( k+ z) i
<pre><code class="language-nginx">server {$ d0 E  s! I2 E' c& x  P- |
    listen 80;
1 @( X% `' ^( ^9 P1 j    server_name your-domain.com;& r* A2 W- O( a/ i/ ~
    # 重定向 HTTP 到 HTTPS
, q+ S' K* R) M    return 301 https://$host$request_uri;! Y  [! ^; f" W5 C& Y# o+ M. [
}
' m0 Y9 m8 a1 `3 x
, O9 x. S; |; I; w; H- Userver {
3 b9 N3 v. y8 O    listen 443 ssl http2;
) p2 t* ], M$ A( d9 q1 \    server_name your-domain.com;+ M7 b+ _0 m! s8 [9 a4 Y( I2 C# H

% P8 t8 u& |$ n0 O- {$ O# i3 f4 ~    # SSL 证书配置(推荐使用 Let's Encrypt)
, J* s0 A$ I+ r- E/ ]    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
2 Q: ^/ c+ y$ \7 n. c& a2 {    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
$ ^7 e( \' x) t: x    ssl_protocols TLSv1.2 TLSv1.3;9 j& _( K2 A) @& L, M; M
    ssl_prefer_server_ciphers on;
/ Y# h7 y+ ~5 H; d. N( R2 L, ~9 S: \
    # 反向代理到 PocketBase4 O# M) m# h( z6 n
    location / {
  [' J+ n: U; _) A8 E        proxy_pass http://127.0.0.1:8090;% W/ A, `, U) p! N4 [1 j( n
        proxy_set_header Host $host;6 c2 w3 I2 j( I3 |  l7 e- g
        proxy_set_header X-Real-IP $remote_addr;; x4 J1 w" `) a; |  `
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;: S  o5 c2 Z3 H0 Z. g0 W5 O; A
        proxy_set_header X-Forwarded-Proto $scheme;0 ~, K5 q1 m# f) b5 S0 [8 ]
    }
* D3 R$ F0 Y& t$ ~" ^8 c}
- A" B, D* Z  H/ \. E</code></pre>& ?5 @" n  @( Q# `3 h3 r0 i% L# A
</li>
9 s, q( W6 Y, c<li>启用配置并重启 Nginx:
6 L* g+ ]2 C9 K" q, }; h# z6 C<pre><code class="language-bash"># 启用配置9 B4 l' W) D) G7 ^
sudo ln -s /etc/nginx/sites-available/pocketbase /etc/nginx/sites-enabled/4 p& ?# y0 P' T) D1 i% B

1 [3 w  y; [) k. X" I& ^9 C# 检查配置语法
5 y" t1 `, b, e: ysudo nginx -t8 Y1 r/ U: ]" O7 n9 ]  X, c; v) \& w
3 Y* D2 D: G& }5 |$ r$ H
# 重启 Nginx
, i& j" q) K2 a1 vsudo systemctl restart nginx
6 j8 O! z9 Y+ f6 \0 R/ H</code></pre>
7 Y- Z% M+ R: A</li>
( }% n6 `% r( p/ p1 O0 p<li>申请 Let's Encrypt 免费证书(可选):- Z2 U3 @1 h/ @8 ^1 F
<pre><code class="language-bash"># 安装 certbot! U% Y1 @0 H/ w
sudo apt install certbot python3-certbot-nginx -y7 ~# Z! W! ?" [  }# [
( E# n1 E# D; [' \% h
# 申请证书
1 V% ~% \: a* s7 @/ y) }. ^sudo certbot --nginx -d your-domain.com
5 t0 ]$ {- g) n2 d2 @9 k( H' Y</code></pre>
. X& V: v6 r9 Q8 J</li>
- a+ X: U. g" O; m+ V+ V</ol>
. q6 o. y4 v& b<h4>5.3 自定义 PocketBase 配置</h4>
0 V3 f6 S/ B( r, u) _4 `<p>PocketBase 的配置文件为 <code>pb_data/pb_config.json</code>(运行后自动生成),可修改以下核心参数:</p>. Z9 `/ ~. k  y& r2 I7 l# W5 e
<ul>" `2 b1 y5 I6 M. t- c+ b/ E
<li><code>appName</code>:应用名称;</li>: K' n' A0 b2 @6 ~( Z
<li><code>api.allowedOrigins</code>:跨域允许的域名;</li>
5 C4 s% V; W/ X9 s<li><code>mailer</code>:邮件配置(用于密码重置、验证等);</li>( Z" ^3 S! @3 T! @$ K# c+ }
<li><code>storage</code>:文件存储配置(默认本地,可配置 S3 等)。</li>
% X; m2 i# c. G! c, P</ul>
3 a8 q9 v7 e& x: y<p>修改配置后需重启 PocketBase 服务:</p>- N# I% d& v: S0 z8 r  H$ p  J8 }
<pre><code class="language-bash">sudo systemctl restart pocketbase' m, Z5 [5 |4 T* g8 M9 u' X2 X; y
</code></pre>
$ c) J8 T! n6 o<h3>6. 日常运维</h3>
1 K' c% t9 q3 u: _( H, ~  d5 o; m<h4>6.1 数据备份</h4>& F* f, r0 d# _8 Z; G7 [
<p>PocketBase 的所有数据(数据库、文件、配置)都在 <code>pb_data</code> 目录,备份该目录即可:</p>
5 {# }. f. O  x5 @, H' ^<pre><code class="language-bash"># 创建备份脚本
  H  o  w: q* V2 `% ~7 B% D( ]2 onano /opt/pocketbase/backup.sh" q% u: W! x; s: H% X9 F1 S
</code></pre>7 v; t) S! X% o; |% {
<p>粘贴以下内容:</p>9 w/ k3 A2 r' g7 ]9 o/ I
<pre><code class="language-bash">#!/bin/bash$ w) g! y/ K2 e( o& G, Z
BACKUP_DIR=&quot;/opt/pocketbase/backups&quot;
: a* t' T' w# h6 p2 xDATE=$(date +%Y%m%d_%H%M%S)4 h7 b" Z$ G$ e! J- d) n5 g
mkdir -p $BACKUP_DIR& Y/ k5 _) a: m% f

4 s$ O* v: L, \! y( b4 S# 停止服务(可选,避免备份时数据写入)
/ A. q+ K) H& f/ R% S: ?sudo systemctl stop pocketbase
: w: i" Y+ R: V; V2 L! Z6 o1 Z7 N7 n) w" o8 p0 f
# 压缩 pb_data 目录) E5 }6 [. l9 l; Z; {
zip -r $BACKUP_DIR/pocketbase_backup_$DATE.zip /opt/pocketbase/pb_data- w0 u2 s. `8 s
9 r* {. L8 i3 T5 `4 I. |
# 启动服务
2 F9 n! |# ?: E8 ?sudo systemctl start pocketbase( A( ~. G1 `5 ^. b$ M

4 ~8 Y2 Z9 g2 i- Y: d' J# 删除 7 天前的备份(可选)
& p9 w4 c5 G" |% S+ v  R, \1 Ifind $BACKUP_DIR -name &quot;pocketbase_backup_*.zip&quot; -mtime +7 -delete# t3 P8 x, a- T
</code></pre>
9 L6 t5 |( E/ U* y- S<p>添加执行权限并定时执行:</p>
3 e$ [8 ^- G- q8 C. u. P) U# R<pre><code class="language-bash">chmod +x /opt/pocketbase/backup.sh: C4 J- C7 l$ t* X/ H
" c# o$ N6 w1 s- Z2 w& I
# 添加到 crontab,每天凌晨 2 点备份, y/ }9 R' q0 b% W  E8 j; f! k
sudo crontab -e, h* p* h7 k! N3 e3 U' L& e
# 粘贴:0 2 * * * /opt/pocketbase/backup.sh
8 J5 a+ z$ m. X8 r) h</code></pre>
) c4 k3 {6 R" W<h4>6.2 PocketBase 更新</h4>& {! D# k! \- J; L4 L. R
<pre><code class="language-bash"># 停止服务0 c* g8 f6 Q- T+ @
sudo systemctl stop pocketbase
4 t7 r3 S! i# V; G
8 k$ V. B2 r4 I& z1 {  ~  p8 C( L# 备份 pb_data(保险)
3 l- i1 S5 v5 C/ ]# M7 M: Bcp -r /opt/pocketbase/pb_data /opt/pocketbase/pb_data_backup
, s1 d' N" E* g6 b5 }
- Y0 V+ E7 X! @+ h; p% ]# 下载最新版本4 {/ y0 M  B) {, }
cd /opt/pocketbase
4 R0 {+ n6 ?4 Y; {wget https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_linux_amd64.zip
! q( X3 `+ x. t6 |( ~  H. Zunzip -o pocketbase_linux_amd64.zip  # -o 覆盖原有文件6 S2 h( [: P* j& _! X9 A
rm pocketbase_linux_amd64.zip) k! X, U# g; z) |$ [& H8 B
% H( m) M" Y( d) K' f
# 启动服务& v8 k% x. c/ G' o
sudo systemctl start pocketbase
' \  i. H/ g$ \( U* Z. a6 o* W0 R, U* p6 j2 O+ j* [1 |1 T
# 验证版本
: v9 h7 y0 _+ E* a6 N2 c/opt/pocketbase/pocketbase version+ S0 ~% c" x9 a/ b& w8 K
</code></pre>
0 b5 J6 v! n! Y' V4 r5 U8 O2 y: G! @<h4>6.3 查看日志</h4>" p" {' h. p: ~' g' a
<pre><code class="language-bash"># 实时查看 PocketBase 日志
2 ^' j% s1 [% I& i( H1 S7 t& hsudo journalctl -u pocketbase -f
: T  J9 J2 `2 K) L/ k
- t* L4 b1 T9 d# V- @- g. O# 查看最近 100 行日志
6 s" P4 W* f& jsudo journalctl -u pocketbase -n 100
# ]6 u) d' d" G# _- a. L</code></pre>
- ]7 L8 d* F) U( V2 j<h3>7. 常见问题解决</h3>
& k3 W/ T( _$ s! e2 {1 U' q* z# M<ol>
! N; ~5 Z  G. T) Z<li><strong>无法访问管理后台</strong>:
% {# R; F4 X+ p  a% v3 j/ m( T<ul>" U% |" d/ u. i/ K- Y3 _. N  B# E
<li>检查防火墙是否开放 8090 端口(<code>sudo ufw status</code>);</li>
2 E0 `! n# w  r) V- ?5 [<li>检查 PocketBase 服务是否运行(<code>sudo systemctl status pocketbase</code>);</li>
4 s# m, x* Z% P0 R, W/ m<li>检查服务器安全组(云服务器需开放对应端口)。</li>
# u: T# g1 E5 Y- s</ul>& |" _, X$ H$ m5 i4 m0 }; o( g
</li>" z2 R1 }+ G) s' r+ K1 n
<li><strong>API 调用返回 403</strong>:# b1 ?0 s8 t9 T1 V" D4 m2 @- x# |
<ul>
$ A- G( P4 w% U6 d% U3 S<li>检查集合的权限配置(管理员后台→Collections→对应集合→Rules);</li>
; {! e  A, u$ u. \- M<li>确认请求头是否携带正确的认证信息(Admin/User Token)。</li>
, w! C; T3 G& M- m2 }2 g; D2 o</ul>
( ]4 s  W) z- A8 j% r</li>8 r* K% M4 S6 O' G3 Z; w  z% i( [
<li><strong>服务启动失败</strong>:
- D& V+ D9 k# @/ @) I<ul>  X$ e: [1 M! n1 g! y( r  ^
<li>检查 <code>pocketbase.service</code> 文件语法是否正确;</li>
7 J5 d% l! v! y9 ?( b9 d<li>检查 <code>pb_data</code> 目录权限(<code>chmod -R 755 /opt/pocketbase/pb_data</code>)。</li>
# |) y1 [* c2 G2 {. \( B5 m</ul>  ^5 ^& C9 C% `( B7 j5 i3 p
</li>9 {8 Q6 h3 C5 ]3 D0 N; `0 ^
</ol>2 {9 b8 k3 C& }5 j$ P% z9 B; V
QQ20260104-124324.webp
匠心独运,千锤百炼,品质非凡。
回复 转播

使用道具 举报

评论3

阿白楼主Lv.1 发表于 2026-1-4 12:54:05 | 查看全部 来自:Error
<h1>PocketBase 在堡塔(宝塔)面板下配置进程守护与端口转发</h1>
/ I/ W6 r" J6 [. X9 E5 [<h2>一、核心需求确认</h2>$ Y2 v% E. {: v' y' j  [& J
<p>你希望在堡塔(宝塔)面板中为 Debian 12 服务器上的 PocketBase 配置<strong>进程守护</strong>(确保 PocketBase 持续后台运行、崩溃自动重启),并设置<strong>端口转发(反向代理)</strong>,让 PocketBase 可通过 80/443 端口或域名访问(替代默认的 8090 端口)。</p>* L# e* `* y. T+ U, W
<h2>二、前置条件</h2>2 _) h8 \/ D; L' C# ^' J
<ol>9 M! `4 G( O9 n3 K. K' p0 Z
<li>堡塔面板已成功安装在 Debian 12 服务器(若未安装,可执行官方脚本:<code>curl -sSO https://download.bt.cn/install/install_panel.sh &amp;&amp; bash install_panel.sh</code>);</li>% ?/ s, Y8 K8 q+ j5 o% g1 i
<li>PocketBase 已按之前的教程安装在服务器(推荐路径:<code>/opt/pocketbase</code>);</li>
# X! B. a" }! k3 A<li>服务器已开放 80/443 端口(堡塔面板默认会开放,可在「安全」模块确认);</li>4 g* Q( W& ]/ q* M3 x- z
<li>若需域名访问,需提前将域名解析到服务器公网 IP。</li>- X" a4 ]# v( P3 e7 F
</ol>
/ j, s# P: f, D<h2>三、配置 PocketBase 进程守护(堡塔面板)</h2>
8 Y2 c9 A: [7 w<p>堡塔面板的「进程守护」功能可替代手动配置 systemd 服务,可视化操作更简单,核心是让 PocketBase 后台运行且崩溃自动重启。</p>
! K- U3 u; p: ^8 S( Q7 O<h3>步骤 1:登录堡塔面板</h3>+ _7 f# f! p/ C/ E0 @5 w
<p>通过浏览器访问 <code>http://服务器IP:8888</code>(默认端口),输入堡塔面板的账号密码登录。</p>0 H7 N) p! f. E% ?$ A+ p  m" V
<h3>步骤 2:进入「进程守护」模块</h3>
3 W  n; Y; ]8 d0 [/ }<ol>
* h$ _5 X1 `) g/ h/ N- [& z! C<li>点击左侧菜单栏的「软件商店」→ 「系统工具」,确认「进程守护」插件已安装(默认已安装,若未安装则点击「安装」);</li>
6 k1 V& y( M0 z6 {" r<li>安装完成后,点击左侧菜单栏的「进程守护」,进入守护进程管理页面。</li>
% D, a2 Q. B) a' |3 A</ol>1 Z' _& x' C4 \/ R7 P9 M6 e# _
<h3>步骤 3:添加 PocketBase 守护进程</h3>% j7 C' D- B3 J. \: a4 Q
<ol>& \% c! [' C9 _/ j7 u
<li>8 L1 d4 z% U4 p. m2 Q# ]
<p>点击页面右上角的「添加守护进程」,弹出配置窗口;</p>
5 `& O6 e" y* C* c- z</li>
, x  ~9 S0 @  {, }<li>
: D* j& C+ A, b% r- z$ j<p>按以下参数填写(关键项标红):</p>
  v; b1 \+ o. Z) y2 Z9 Z<table>) b) l" S1 y2 _9 m  |0 W7 }
<thead>/ E, X  O  W- o: d8 F2 \
<tr>4 O5 q: e1 X" d% h. T( }
<th>配置项</th>
: _# W% l6 C! A+ s<th>填写内容</th>
% O# z( x1 I* w& w6 i# x+ u' K</tr>' |4 p2 X0 r1 B9 l" y3 X( O  E3 D4 J
</thead>
8 i3 A! b* e' n$ b+ r- r<tbody>6 Y8 ^5 F( p5 O$ n. E6 q+ t
<tr>* S5 A: [; @& |7 c! \6 L$ }
<td>进程名称</td>5 {; n8 {3 |/ h: r1 ^7 g4 c; X
<td>PocketBase(自定义,便于识别)</td>4 |& u, F0 b6 F4 x1 n5 C) N2 X8 }
</tr>
, B$ z0 ?' h' q. i4 [<tr>9 y  }$ z" q6 \: k5 @# E' ]% b
<td>运行目录</td>; D$ V) J0 L. [8 c* o
<td><code>/opt/pocketbase</code>(PocketBase 二进制文件所在目录,需和实际路径一致)</td>
1 s6 W, A: X& F! {  _+ U( @* u</tr>: G: l: a+ |7 J+ W
<tr>! h8 F' S1 H; ~. d
<td>启动命令</td>
" E3 b- D" a$ h, ?0 U1 @<td><code>./pocketbase serve --http=127.0.0.1:8090</code>(绑定本地回环地址,更安全)</td>7 H- N1 r% x" b! E
</tr>% }7 b6 f& [, M6 ]9 X% R
<tr>* M( N- u' ?8 ?9 I& }2 f  C
<td>停止命令</td>
& P$ f! z& V) Z  F7 I% u<td><code>pkill pocketbase</code>(可选,用于手动停止进程)</td>
& b( E2 P# h) \  t  E</tr>4 e' @, F) h/ A1 L
<tr>" Q4 W% d. i& r+ q: u) N' _
<td>日志文件</td>
2 L/ H) u" x6 p$ j, O7 f<td><code>/opt/pocketbase/pocketbase.log</code>(自定义日志路径,便于排查问题)</td>
1 [) {8 w5 K$ \* x# F</tr>+ C, N8 m" \. x" ?, S6 ~
<tr>
% U3 b$ f" X/ G- n! I<td>错误日志文件</td>
/ a  \: Z" G' F/ C6 T<td><code>/opt/pocketbase/pocketbase_error.log</code>(可选,单独记录错误日志)</td>
; D5 K+ n8 C# ~8 L</tr>8 l; K* x3 N3 t( C' K% }2 a+ O
<tr>
9 d% E" @8 u6 {<td>自动重启</td>4 D: P' i4 F- x3 y3 }. O& D+ e$ M" \
<td>开启(必选,进程崩溃后自动重启)</td>
& c" |& s2 f3 O; Q</tr>
' G' U% z% D/ T) @<tr>& w6 B! L# p4 i5 i3 Z
<td>重启间隔</td>
7 l, t# @+ b2 f3 Y7 i. f4 r/ a<td>5 秒(默认即可)</td>
7 F. T, S3 j  T6 f; t</tr>; P2 G; r  U" f: e1 a, a& F
<tr>% G8 P& D% M* A
<td>启动用户</td>1 C, F( v5 ?6 ^: Y) p+ v+ V
<td>root(或你创建的非 root 用户,需确保该用户有 <code>/opt/pocketbase</code> 目录权限)</td>
; S* g6 e9 I/ l- o2 G& _</tr>
; ]4 F8 U% \1 B+ H</tbody>0 @6 J" H$ M) h
</table>6 M0 _7 q# Q* z9 @$ \: B  l
</li>4 ]4 d& Z* o) x
<li>9 h- u. |7 I' w3 P8 Y6 U2 g6 v2 U; k
<p>点击「提交」,完成守护进程创建。</p>
0 P; a% `' C( S$ s. n</li>
$ ^: P# t; ?( \6 I- E8 b% q</ol>
0 n2 U, j3 _2 E' B0 o  `( o5 o+ C6 m<h3>步骤 4:启动并验证守护进程</h3>/ ^- o" U  s$ S; Z# l( W) R
<ol>
8 j( w2 G* X* X, ?1 A; l* `<li>在「进程守护」列表中找到刚创建的「PocketBase」进程,点击右侧的「启动」;</li>
$ I3 j3 H4 i5 l" h8 |9 f& ~<li>启动后,进程状态会显示「运行中」,可点击「日志」查看运行日志:
9 n1 x1 V- ?2 Q* r; l<ul>& {2 m8 o- _/ F
<li>若日志中显示 <code>Server started at http://127.0.0.1:8090</code>,说明 PocketBase 已通过守护进程成功运行;</li>5 N: g) O! a$ k5 k0 p
<li>若启动失败,检查「运行目录」「启动命令」是否正确,或查看「错误日志」定位问题(如权限不足可执行 <code>chmod -R 755 /opt/pocketbase</code>)。</li>. Z/ W$ b4 W( k& m+ z( `' b6 C
</ul>
- q( n; T3 |5 l4 `</li>) i1 @7 V; B7 l6 G% K' z
</ol>: q+ Q; p$ c; p& i' s
<h2>四、配置端口转发(反向代理)</h2>
( v6 M6 D: t; T! y2 K0 u2 `<p>PocketBase 默认监听 8090 端口,直接暴露该端口不够友好,通过堡塔面板的「反向代理」可实现:</p>
$ y# \) r) o( S! q7 J1 ]" {( r<ul>
4 J/ D5 S" x$ X' o' C! s) v<li>域名访问(如 <code>https://your-domain.com</code>)→ 转发到 <code>127.0.0.1:8090</code>;</li>* C7 {+ X3 Z$ |) n5 R) y, [% \
<li>80/443 端口(默认 HTTP/HTTPS 端口)→ 转发到 8090 端口;</li>9 A& d+ m+ C: h% I! \2 O5 v
<li>同时可一键配置 SSL 证书,实现 HTTPS 访问。</li>
/ I! ?+ Q$ V) r0 C( Z  J</ul>
8 G( T* f. Q4 N+ O4 j7 Y<h3>步骤 1:添加站点(域名绑定)</h3>6 \" I6 Y5 t* V
<ol>
( {4 W3 D" w5 w; S$ r# x<li>
. S( r* Z' @: f6 Q1 C6 o* k+ g<p>点击堡塔面板左侧菜单栏的「网站」→「添加站点」;</p>
# f) x3 ~5 ^' O/ z* {9 l+ o: D</li>5 S6 `+ h6 w. ?. f1 v# [
<li>
" H$ [, O4 u1 M- G: t! L# u<p>填写站点配置:</p>5 L  M4 w  q$ [+ U/ S0 Z- w( `
<table>/ g' T# ?6 L1 i1 b3 N6 N8 f; Z. x4 K
<thead>, ~& ]- e3 }  T" I5 j% W* ~) @- f5 ?
<tr>
9 \6 |5 u- l  X* x<th>配置项</th>1 C0 _3 I- I  U  a% H
<th>填写内容</th>
$ W: M" i% W. B3 n</tr>; G8 z( T" G/ a7 i( P
</thead>+ c, ^% O/ k! J, h. N! ^2 z
<tbody>
. y9 d: n8 S& x3 u. ?2 w4 h7 R<tr>7 B, i5 t4 P4 k6 r
<td>域名</td>
& v4 ?6 ]5 `7 n4 S/ X8 d! z<td>你的域名(如 <code>pb.example.com</code>,若无需域名可填服务器 IP)</td>
1 S7 F+ |  d" A4 T* Y' T, k</tr>
" v' A0 X- X) G9 R" b<tr>
9 p* x9 n+ y# g! r' g, S+ H<td>备注</td>
8 S* _8 M8 B; H: b<td>PocketBase 反向代理(自定义)</td>
# Z9 c+ [' N. S3 z' [8 Z- c  I% [9 ^</tr>3 D4 H  }& @. ~  g4 r9 }- P
<tr>
3 x' A6 `+ M7 T. B: z' R0 F<td>根目录</td>
8 _) @6 Y9 F" n4 |' }<td>任意(反向代理无需实际网站文件,如 <code>/www/wwwroot/pocketbase</code>)</td>
2 t3 {5 Q$ Z( W' w0 s</tr>
( t* U# S, R7 `6 H<tr>
7 ~$ s. l7 l% l" t' c<td>PHP 版本</td>4 f" e: g: M9 J6 l, t: A/ P% O
<td>纯静态(无需 PHP,选择此项)</td>
* |/ @0 Q. }8 w# r' L' @% a</tr>: C6 ~+ K' O) h
<tr>
7 ?( y; F! S2 ]% B' z( F<td>数据库</td>$ |) y: V5 h' E/ \, l$ s5 }
<td>不创建(无需)</td>
+ x% d9 x: Z. o- _</tr>6 y8 m* N. A' T3 o( q
<tr>. d( z/ ?# c. h3 c0 i
<td>FTP</td>1 o0 }$ U- O9 q6 ~9 d6 Z6 y: c
<td>不创建(无需)</td>6 @0 x) M- y: T) H9 o6 R% h
</tr>" c+ k" g* u# }6 u9 k
</tbody>
4 M: }# c* V8 x</table>
$ F* e) \$ @9 s" A</li>+ s; S, }1 n4 T' L4 D8 X
<li>
3 M6 @9 q1 \3 X7 P, T- K* C. w<p>点击「提交」,完成站点创建。</p>
+ w# f% f& Y/ N</li>6 x' O0 t0 d" K- L4 t% g
</ol>( X, z6 `4 M  ?- k- [
<h3>步骤 2:配置反向代理(端口转发)</h3>
0 i) _, @5 G4 d<ol>
& r" B  o. \- \% W; T2 F( H<li>" A7 r/ ?( H* h/ d; W
<p>在「网站」列表中找到刚创建的站点,点击右侧的「设置」;</p>
; C+ p" @! k1 J: }; N8 h</li>; F0 a" [3 u3 c. C
<li>
& u/ l/ K6 Q, D! ~0 |1 N  L<p>点击左侧的「反向代理」→「添加反向代理」;</p>, Y, S+ d3 W) O6 j0 p
</li>
" s0 L4 V+ t  }$ N<li>
% R/ y) G1 }+ O3 R+ y. ]<p>填写反向代理配置:</p>
8 U3 `- X- O8 V<table>6 u) L+ t: A" [" X& I( T4 Y1 @
<thead>- q! [9 `* s1 g6 }, {
<tr>% v, K1 y& K8 T8 h0 o" f
<th>配置项</th>
6 A; u: ~1 v9 Z6 m  C7 v<th>填写内容</th># [6 t0 ?- X3 F' r
</tr>
2 S# L. K, W  t: j</thead>
3 c3 ?# @$ k7 [2 T<tbody>
6 O3 S) X2 M! b6 l# v) _<tr>
7 M* K2 L. o# T" `3 s5 L<td>代理名称</td>9 r7 J* u! @5 X6 P+ ]
<td>PocketBase(自定义)</td>) s$ @4 t. z/ t5 i
</tr>" m* l0 g5 W. |3 r
<tr>
; P' t6 J7 @4 N4 t<td>代理目录</td>
, B0 ]+ ^7 f8 ]0 ?3 K* p5 r5 S5 m<td>/(根目录,转发所有请求)</td>% M$ [2 l9 U- }$ R$ B. ?' n
</tr>
' }1 J% J2 _* `( a* W: s<tr>
6 t6 t9 k- V. d: e. n7 m6 ^7 |<td>目标URL</td>
" A0 B) k8 [; E, X( ?+ K+ v  y<td><code>http://127.0.0.1:8090</code>(PocketBase 运行地址,和守护进程启动命令一致)</td>
, }9 I/ x( k1 j5 R6 o# g) ^</tr>
0 u% Z3 O% F( C* E<tr>& ]6 Y0 K0 T$ }( L) F
<td>缓存</td>1 E/ A% j( k6 z; x3 I
<td>关闭(避免 API 数据缓存)</td>1 H% k, m( |( P+ N8 ^& Z* d2 m
</tr>
: N' R) B) j8 a, a  g<tr>% r6 K8 _+ Q& f0 D
<td>反向代理参数</td>
& V2 m" Z. _# k<td>点击「添加自定义参数」,新增以下参数(解决跨域/Header 传递问题):<code>proxy_set_header Host $host;``proxy_set_header X-Real-IP $remote_addr;``proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;``proxy_set_header X-Forwarded-Proto $scheme;</code></td>
9 m9 ]  F# d. C' f' v/ o</tr>
- z5 ?" p1 }% a  I5 P0 Q  p6 L</tbody>
, I* U# p' d' A: n+ R</table>8 G: B' t6 H% i# _* d: y. d
</li>. q6 g  W+ V: B% E/ c# G2 ]! z6 f
<li>/ l  H8 o- a6 ]6 N
<p>点击「提交」,反向代理配置生效。</p>/ u, [+ T$ ~* ]! a
</li>
+ D# h! g5 s* M1 ]8 R, f9 R* D; |</ol># `- C( C8 P. k8 U  u" J: W2 W
<h3>步骤 3:配置 SSL 证书(可选,推荐)</h3>
5 {. L" A2 \0 }<p>为了安全访问,建议给域名配置 SSL 证书(堡塔面板支持一键申请 Let's Encrypt 免费证书):</p>* ?. t* p+ O( Q- K7 }
<ol>) |. ]( Y, l* [2 B* k* Y
<li>在站点「设置」页面,点击左侧的「SSL」;</li>! P5 v! g  Z8 e) ^" Y, x( l
<li>选择「Let's Encrypt」→ 勾选需要申请证书的域名 → 点击「申请」;</li>
5 w! ~$ `# c! o- T<li>申请成功后,开启「强制 HTTPS」(自动将 HTTP 请求重定向到 HTTPS);</li>
; Z0 ^( ]* d* G8 K<li>点击「保存」,SSL 配置生效。</li>7 i" m7 d6 Y9 z  @9 {. a2 B; y& O9 ?
</ol>
! C) G& D3 L6 W. c$ {<h3>步骤 4:验证端口转发</h3>
/ H: r: a3 i$ D: C' y8 K<ol>
4 j0 }' a! M0 C" d: Q7 U1 h<li>访问配置的域名/IP:
6 B9 r# g, i* @8 q' Q, d<ul>
/ o, A8 p9 V0 j5 o3 k<li>管理后台:<code>https://你的域名/_/</code>(替代 <code>http://服务器IP:8090/_/</code>);</li>% Y4 G/ T3 p4 Q2 a2 c
<li>API 接口:<code>https://你的域名/api/collections/users/records</code>(替代 8090 端口);</li>
+ ?0 Q- y/ @& b/ n</ul>
! e: t8 s9 R6 U" h</li>
7 e3 ]- q  T6 ~" l, s$ t+ P<li>若能正常访问 PocketBase 管理后台或 API,说明端口转发配置成功。</li>( z5 v- M' J, l; X- l' D. S# R
</ol>/ h% w7 ]6 P; N* v. X$ e9 n3 c
<h2>五、常见问题排查</h2>' r( ~7 p9 q% ?3 ?. p
<ol>
3 W9 |* P' O; E<li><strong>守护进程启动失败</strong>:. l1 ?) q! ?2 c) I( W
<ul>* m0 d8 ^9 s1 k4 N( Z
<li>检查「运行目录」是否为 PocketBase 二进制文件所在目录;</li>
; H8 J6 \1 k9 M9 ]9 ?+ s4 H- V<li>检查启动命令是否正确(如 <code>./pocketbase</code> 路径是否存在,可在堡塔面板「终端」执行 <code>ls /opt/pocketbase</code> 验证);</li>
8 F% l, s" T; u" m& Q<li>查看「错误日志」,若提示权限不足,执行 <code>chmod +x /opt/pocketbase/pocketbase</code> 赋予执行权限。</li>3 }. `6 [/ l& u7 `: B5 Y
</ul>
! O+ f; {% r, U, u3 B" z</li>
$ X/ b5 W+ U  |0 H<li><strong>反向代理访问 404/502</strong>:+ B" m1 d# ]2 y0 F, p, H
<ul>
- _5 N, v% E* }6 a; }7 z<li>502 错误:PocketBase 守护进程未运行,先确认进程状态为「运行中」;</li>
) M; A3 q, S% |8 M( E! p- N- P6 e<li>404 错误:反向代理「目标URL」填写错误(需为 <code>127.0.0.1:8090</code>,而非服务器公网 IP);</li>5 u& R5 h3 a. M" q
<li>跨域错误:检查反向代理「自定义参数」是否添加完整的 Header 配置。</li>
, z/ z4 {8 t  [3 O: Q! z1 Q</ul>
) d$ g- F1 Z1 x0 C' R# @  F</li>
  n; i0 c: Z+ h$ M( F+ ]<li><strong>域名无法访问</strong>:5 ]6 G& M/ d8 l
<ul>
7 O3 R1 [& s& v' o0 L<li>确认域名已解析到服务器公网 IP(可通过 <code>ping 你的域名</code> 验证);</li>
+ I' C6 Z- F6 x<li>确认服务器安全组/堡塔面板「安全」模块已开放 80/443 端口。</li>
7 m) J  A# d9 `$ s4 O$ \' ^</ul>
0 V$ [+ \3 E1 f  {</li>
0 A- W. l7 I# ~3 n  A</ol># u0 M( u' k- |( u+ ]
匠心独运,千锤百炼,品质非凡。
回复

使用道具 举报

diggerLv.9 发表于 2026-1-4 12:57:08 | 查看全部 来自:Error
<h1>PocketBase 保留目录说明 &amp; 钩子(Hook)调用方式与示例</h1>* u. ^& S) E: Q
<h2>一、核心需求确认</h2>
$ c4 w& _. }9 O* Y<p>你希望了解 PocketBase 运行过程中自动生成/识别的<strong>保留目录</strong>的名称和具体作用,同时掌握 PocketBase 钩子(Hook)的调用方式,并通过实际示例理解钩子在业务场景中的应用(如数据校验、事件触发、自定义逻辑等)。</p>
5 d: ]2 W3 J! U& `<h2>二、PocketBase 保留目录详解</h2>& I) D2 c+ ?! d/ l
<p>PocketBase 运行时会在其工作目录(如 <code>/opt/pocketbase</code>)自动生成/识别多个保留目录(文件名固定,PocketBase 会优先读取),所有核心数据、配置、自定义逻辑都集中在这些目录中。以下是所有保留目录的名称、作用及关键细节:</p>6 a& @$ {3 A* {( @0 Y& e; G9 [# I! A
<table>
6 `) j* ]8 H* r, Y<thead>
( B0 ]3 ?3 |1 ^" g2 p9 H<tr>- U& u$ J5 V; M% j" \) W2 @; B
<th>目录名称</th>) {5 J3 m/ k! {+ q1 [) P
<th>核心作用</th>0 O6 `5 v  ^- c! R- L- |4 Q& ~
<th>关键文件/子目录</th>/ {" V1 r! E7 y4 D! [1 R3 _2 f$ t
<th>适用场景</th>
: m- ]* L/ D$ f& v) a' G5 u</tr>5 r( z4 w3 m$ \- W4 a
</thead>
9 s8 E! @) T7 D9 |<tbody># Z4 H& X& A2 U6 q$ N
<tr>! `% j0 ^  ^; n/ F4 @4 |# M
<td><code>pb_data/</code></td>
# C: Y; j' I. {) H$ S2 T<td><strong>最核心目录</strong>,存储所有持久化数据(数据库、配置、文件、日志等)</td>3 f9 V3 O1 a: q: c' I1 C1 _
<td>- <code>pb.db</code>:SQLite 核心数据库(存储集合、记录、用户等)- <code>pb_config.json</code>:全局配置文件(应用名称、跨域、邮件等)- <code>storage/</code>:文件存储目录(上传的图片/文件)- <code>logs/</code>:运行日志(可选)- <code>pb_auth.json</code>:认证相关配置</td>
# D' m  ?) ~3 v& p# ?4 Z6 ^<td>数据备份、配置修改、文件存储管理</td>; @$ l9 v+ L/ ~1 I3 |
</tr>
5 c& r# M/ _, v/ B<tr>
, P; t3 y# D7 {<td><code>pb_hooks/</code></td>+ p) N4 a5 t' A1 u! d
<td>存放 JS/TS 钩子脚本,PocketBase 启动时自动加载,用于扩展业务逻辑</td>7 _# x! n% Z9 t
<td><code>*.js</code>/<code>*.ts</code>(如 <code>users.hooks.js</code>)</td>
0 I9 @0 d0 X8 |- U9 \3 H<td>数据校验、事件触发、自定义认证、请求拦截</td>! \$ Q, L9 _" E& W
</tr>' k* C' F" b' k( f3 Y
<tr>) m$ t6 {. Q1 t! Z$ K. _# g
<td><code>pb_migrations/</code></td>/ T8 P+ \# S+ p: D6 b7 r  P" h
<td>数据库迁移脚本目录,用于管理集合结构变更(版本升级/手动修改表结构)</td>: c6 ]: v( n$ ]9 E( W5 u" N3 V8 K
<td><code>*.js</code>/<code>*.ts</code>(如 <code>20240104120000_init.js</code>)</td>
+ Z, N. b/ |7 n* Y$ y% x8 K/ _* ]<td>生产环境集合结构变更、版本迭代</td>" z/ l4 }5 f' ?/ l. M8 ^& |2 B+ A2 W# U
</tr>. y0 O9 X& }1 U: V' c, h: |
<tr>
( O9 i% d: S+ F& u$ J+ P% _<td><code>pb_public/</code></td>) P4 D8 S0 J0 A  B, U8 S* S' r+ {5 [( R
<td>静态文件托管目录,可通过 URL 直接访问(无需认证)</td>
5 Q2 {+ v  z3 p<td>任意静态文件(如 <code>index.html</code>、<code>logo.png</code>)</td>
* @( v; J0 M6 J/ j1 H<td>托管前端静态页面、公共资源(如图片、JS)</td>  n6 J6 i! K; B* W" K" N' p
</tr>0 [) B# G4 h9 Y- s% E* P& H3 Q/ H
</tbody>/ s. `6 p+ [9 s# m5 [% u
</table>" ^% t5 A' B9 Z7 Y' n: O
<h3>各目录详细说明</h3>
* Q9 [3 |4 Q: R6 Z) e$ ^<h4>1. <code>pb_data/</code>(核心数据目录)</h4>4 e' X0 g- X) G2 r* p: l1 \- t8 e1 e
<ul>
; a; d. k1 [8 L' t' r<li><strong>不可删除</strong>:删除该目录会丢失所有数据(数据库、配置、上传文件);</li>7 Q! g8 [! z# U
<li><strong>备份优先级</strong>:日常运维只需备份该目录即可完整恢复 PocketBase 所有数据;</li>
6 ^, }5 i$ }3 W2 l" j<li><strong>关键文件说明</strong>:
# ]  ?) F$ Y4 f1 E5 ]<ul>! v+ s9 d! n" q5 D2 q. j; r" `/ u
<li><code>pb.db</code>:SQLite 数据库文件,存储集合定义、记录数据、管理员/用户账号等核心数据;</li>/ c8 f' Y* I; ]( }6 W
<li><code>pb_config.json</code>:自动生成的配置文件,可手动修改(如跨域允许的域名、邮件服务器配置),修改后需重启 PocketBase;</li>
- i/ g& D$ D; @3 o6 B8 m7 c- V<li><code>storage/</code>:默认存储用户上传的文件(如集合中「File」类型字段的文件),路径对应 API 返回的 <code>fileUrl</code>;</li>+ @& c% n+ H2 Y3 @" M
<li>权限要求:运行 PocketBase 的用户需有该目录的读写权限(如 <code>chmod -R 755 pb_data/</code>)。</li>
6 j$ t" ?* P3 `) _</ul>
5 I& D) a# o4 e9 S% _) b3 v/ n7 M</li>' O" u3 s- `* b3 [. p/ v# o) m' }
</ul>; l3 U# Q( F6 E; j1 }  Y
<h4>2. <code>pb_hooks/</code>(钩子脚本目录)</h4>$ w0 d0 K% M( F; R. w2 ~7 C
<ul>6 B: }  g! D+ \8 \( l9 Q2 p
<li><strong>自动加载</strong>:PocketBase 启动时会扫描该目录下所有 <code>.js</code>/<code>.ts</code> 文件并执行,无需手动配置;</li>
+ a" n6 i/ m1 q! c" e<li><strong>运行环境</strong>:基于 Go 内置的 ESModule 运行时,支持大部分 ES6+ 语法,可直接使用 <code>console.log</code> 调试;</li>
  b) ^3 m9 W8 m: S) P* ?<li><strong>无依赖</strong>:暂不支持 npm 包,需用原生 JS/TS 编写逻辑。</li>
3 }" R4 X. ]' p" @" A/ ~; X</ul>
, |8 R" O; [: j# O0 V<h4>3. <code>pb_migrations/</code>(数据库迁移目录)</h4>" ]/ A0 T$ X, [8 v2 r) O. g4 M
<ul>' G, G& x6 S5 ?
<li><strong>自动生成</strong>:在管理后台修改集合结构(如添加字段)时,会自动生成迁移脚本;</li>/ N1 F" m3 `/ c* W# a) [
<li><strong>手动执行</strong>:可通过命令 <code>./pocketbase migrate up</code> 执行未应用的迁移脚本;</li>" r  Z( R  L8 G: O/ T4 |2 p( `3 D
<li><strong>回滚</strong>:支持 <code>./pocketbase migrate down</code> 回滚最近一次迁移(需脚本支持)。</li>
, O+ y3 d1 J, Q' g8 G/ l1 y7 h</ul>
4 E/ V0 w3 w" E; a; e* j3 S# n5 ?<h4>4. <code>pb_public/</code>(静态文件目录)</h4>
$ s) c" `3 C' j; ], L* [<ul>' W# y! K' F6 R+ C
<li><strong>访问方式</strong>:文件路径对应 URL 路径,如 <code>pb_public/logo.png</code> 可通过 <code>http://域名/public/logo.png</code> 访问;</li>& Y7 s7 s5 @: l" j( e
<li><strong>权限</strong>:所有文件无需认证即可访问,适合存放公共静态资源(不建议存放敏感文件)。</li>& L* o% a& ]5 T. P6 j6 A. a1 m
</ul>9 J$ c! C6 Q7 _6 j) z
<h2>三、PocketBase 钩子(Hook)调用方式与示例</h2>- M8 V9 ]6 d' f
<h3>1. 钩子核心概念</h3>+ [( U7 z# f1 D
<p>PocketBase 钩子是<strong>服务端事件驱动脚本</strong>,可拦截/处理系统核心事件(如数据创建/更新、用户认证、服务启动等),实现自定义业务逻辑(如数据校验、自动填充字段、日志记录、权限控制)。</p>
3 N9 h' d, P/ r! Q, T1 n  v<p>钩子分为两类:</p>
; v2 l  e. H! R<ul>
) `( o' U( B; {, p# t9 s1 Q<li><strong>集合钩子(Collection Hooks)</strong>:针对特定集合的操作(如 <code>users</code> 集合的创建/更新),最常用;</li># j; a  j7 ^& O
<li><strong>全局钩子(App Hooks)</strong>:针对全局事件(如服务启动、HTTP 请求拦截、用户登录)。</li>9 f; D( Q% Q* I4 A4 D2 o7 a
</ul>7 o8 A" }* \- k' T1 a
<h3>2. 钩子基本使用步骤</h3>
/ w/ r3 L" \' l5 P2 q<ol>* T+ v2 Z  c9 i7 k& z
<li>在 PocketBase 工作目录(如 <code>/opt/pocketbase</code>)创建 <code>pb_hooks</code> 目录:4 S9 V- o# _6 _
<pre><code class="language-bash">mkdir -p /opt/pocketbase/pb_hooks
3 [4 _! u, ^3 m+ [) r# A- ^</code></pre>
3 y1 [8 c& E) ]8 P" G3 F2 I7 e</li>
. R/ c0 Y2 I/ U* k: b# g<li>在 <code>pb_hooks</code> 目录下创建 <code>.js</code> 文件(如 <code>users.hooks.js</code>);</li>
6 A8 Y$ H  R' Z9 N5 @* @0 q4 U<li>编写钩子逻辑,保存后重启 PocketBase 守护进程(堡塔面板「进程守护」→ 重启);</li>
: h+ o5 m  x% M$ N+ p/ f: k6 @3 {- }$ n<li>测试触发条件(如创建一条用户记录),验证钩子是否生效。</li>
: I0 n& i; _" ?4 [  T' q: [% I</ol>
1 V# q$ M, E0 e* m<h3>3. 常用钩子示例</h3>
. d* C8 q4 \0 A" `  I<h4>示例 1:集合钩子 - 数据创建前校验(必填字段+格式校验)</h4>" I) B+ C# F/ w% X# C  [: C
<p>场景:<code>users</code> 集合创建记录时,强制校验「email」字段格式,且「username」字段不能为空。</p>
5 o/ d" D1 q! l<p>创建 <code>pb_hooks/users.hooks.js</code>:</p>. y. M6 `" F& i# J; q) j# F
<pre><code class="language-javascript">// 监听 users 集合的 beforeCreate 事件(创建记录前触发)
8 O* z* t2 p7 o  c( WonRecordBeforeCreate((e) =&gt; {) J. i8 l  J- ~# E3 T/ T9 w
  // 仅针对 users 集合生效# q2 H$ Z# e% x% r
  if (e.record.collectionName !== &quot;users&quot;) {3 \6 p% t+ _4 Z: [
    return;
5 n) ?9 R" n1 z* J, ^4 S  ^( h  }
5 I& w0 z& |4 Y, L/ s
) {2 Z1 ?7 {1 Z. N  // 1. 校验 username 不能为空, m: R% Z4 g% y# F2 A  ~, [
  const username = e.record.get(&quot;username&quot;);
  h4 W+ R( r- N1 c9 V  if (!username || username.trim() === &quot;&quot;) {2 {& J' ^# C6 w# T4 s; O" n- ]8 p
    throw new Error(&quot;用户名不能为空!&quot;); // 抛出错误会终止创建操作,前端会收到该错误信息+ l! {6 F. T$ l* t* h# C5 t7 o" n. ^
  }6 q4 X# o- a- z2 s" r
( P6 O9 K  c* i3 \% X
  // 2. 校验 email 格式
5 L: O& \9 ^7 A  R  const email = e.record.get(&quot;email&quot;);
0 I" @4 `9 k4 c& q. b% k, y  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;+ c, [3 N. j7 A( q
  if (!emailRegex.test(email)) {  Z3 E7 Z$ x0 |1 e) E, c. o/ s
    throw new Error(&quot;邮箱格式不正确!&quot;);
* x7 A; c# Z. V' ?8 z) u$ q  }
" O7 a* }( C8 C' b6 u4 l; v6 j/ [
8 i! t) d! h( B/ k( g3 K  // 3. 自动填充创建时间(无需前端传参)  |# C& w& U9 U, J
  e.record.set(&quot;created_at&quot;, new Date().toISOString());8 o( c% W' J. b2 [8 s, k  H5 S
});
5 H! v& e, F3 f% f/ o</code></pre>: i* ~) p! C4 R- U" Q6 I5 `4 y) P
<p><strong>触发方式</strong>:调用 <code>users</code> 集合的创建 API 时自动触发:</p>
, ~$ n& c" C' Q6 A& m  n: [8 {<pre><code class="language-bash"># 测试:传入错误邮箱,会返回「邮箱格式不正确」
% [! w  m7 h5 o6 Lcurl -X POST http://域名/api/collections/users/records \
; w/ I: w" u! e2 h. C  -H &quot;Content-Type: application/json&quot; \
; k+ U( f& Q/ @; v2 y  -d '{&quot;username&quot;:&quot;test&quot;,&quot;email&quot;:&quot;invalid-email&quot;,&quot;age&quot;:25}'
( g7 E8 R9 ]* z</code></pre>7 i6 W! E5 X9 v2 E) ]
<h4>示例 2:集合钩子 - 数据更新后记录日志</h4>
- D5 T# _( h/ E, E<p>场景:<code>users</code> 集合记录更新后,自动将操作日志写入 <code>user_logs</code> 集合(需先创建该集合,包含 <code>user_id</code>、<code>operation</code>、<code>update_time</code> 字段)。</p>5 V! ^2 f2 P7 ^
<p>创建 <code>pb_hooks/users.hooks.js</code>:</p>) x" b" d. ]! d4 c2 N1 m) p
<pre><code class="language-javascript">// 监听 users 集合的 afterUpdate 事件(更新记录后触发)/ x' F9 Y7 g2 C' N- ?
onRecordAfterUpdate(async (e) =&gt; {/ G6 M  c' [/ M0 c7 H' J' |9 u
  if (e.record.collectionName !== &quot;users&quot;) {
4 G" t+ E# ^* p7 G" g    return;
0 E+ G: z2 t& y* m8 H( q  }
% I/ n2 r+ J& w' ]8 n+ Y- D9 z" j8 A" g) R8 b0 u
  // 获取更新的用户ID和操作时间  X$ F3 M& p2 K* e! i5 s
  const userId = e.record.id;
8 W. k, S, @- g  const updateTime = new Date().toISOString();
' I3 u. R+ G% z  ]$ L. _6 \: e, G* s! G+ f
  // 写入日志到 user_logs 集合
8 O8 n. i  F: S8 z. Z. V! I  await $app.dao().createRecord() p5 F- j9 n, L7 b+ D
    $app.dao().findCollectionByNameOrId(&quot;user_logs&quot;),4 F8 G; N& d& R9 ~: f
    {& `- m2 p* E0 b7 n  o1 O+ z' Z
      user_id: userId,
/ x# ~1 x* X0 }. X& z      operation: &quot;用户信息更新&quot;,3 P' ~+ O8 e5 C7 q# _- J
      update_time: updateTime,+ A; J! {6 L! X6 e. x8 r
    }
$ T9 l& ]! w- K# E4 h  );
% ]1 g8 d) z# r7 p1 l- z
  G$ l; a; C* P0 o3 b+ a  console.log(`用户 ${userId} 信息已更新,日志已记录`); // 日志会输出到 PocketBase 运行日志
2 f9 c/ k8 p, i5 m/ ?});
: `+ y$ k" p2 e2 i% b! P" B</code></pre>* n+ p; Z4 q1 Z- P* ^
<h4>示例 3:全局钩子 - 服务启动时初始化</h4>4 s8 f* T4 W& J
<p>场景:PocketBase 启动时,自动检查 <code>settings</code> 集合是否存在默认配置,不存在则创建。</p>/ R; m$ q8 |8 _' T
<p>创建 <code>pb_hooks/app.hooks.js</code>:</p>
# R( H# c6 e: K<pre><code class="language-javascript">// 监听服务启动后事件7 ^; w% @! `8 N6 D
onAppAfterServe((e) =&gt; {
4 q1 f  h6 b0 z' y( \6 d  console.log(&quot;PocketBase 服务已启动,开始初始化默认配置&quot;);
1 L8 ^" }) i! v5 M" u
$ s/ A' u/ Y/ V) N- `. z  // 获取 settings 集合7 |5 ^8 \* A" S9 w' ^  _5 r3 p  Y
  const settingsCollection = $app.dao().findCollectionByNameOrId(&quot;settings&quot;);2 k. i6 e9 C9 T. E& N. |
  if (!settingsCollection) {1 C) t# D5 f( F2 ^* t8 A! X; m, n
    console.log(&quot;settings 集合不存在,跳过初始化&quot;);; e" M* o6 h0 M. o" r# C
    return;; V% l7 w3 w2 K9 D/ h4 ^4 ?
  }0 z* I9 }% Z. @+ D
, j" v- {" Z" [6 d8 J7 T# z
  // 检查是否已有默认配置+ D& A( z$ b+ }. C8 i8 t
  const defaultSettings = $app.dao().findFirstRecordByFilter(' O9 F/ a$ y0 _% o6 ~
    &quot;settings&quot;,
6 h: x9 K7 B7 L7 D1 X    &quot;key = 'site_name'&quot;,- h, ^- E# Q! m. s& i
    &quot;&quot;  i( Y' G2 O! S. d: q6 \, }: F# x
  );
- _( C* Q  q5 X2 D# T, k/ K+ o3 U1 |& F* j0 i3 z0 {
  // 无默认配置则创建6 S1 }+ F+ t& P) p5 S
  if (!defaultSettings) {
6 U6 [  D$ Y, o% f( a- x0 Y    const record = new Record(settingsCollection);
5 o' D6 P, L- |1 L7 e9 p    record.set(&quot;key&quot;, &quot;site_name&quot;);
0 I9 [7 f4 f4 f* ?! p  ?8 M0 V    record.set(&quot;value&quot;, &quot;我的 PocketBase 应用&quot;);
% D, O$ w" ]) S/ F+ o    $app.dao().saveRecord(record);$ q: d; ]& M3 n; A- f9 N# N
    console.log(&quot;默认站点名称已创建&quot;);8 }/ r+ V' _# g6 T
  }! C% \6 E+ ~# z$ S: X  X- g
});
5 [/ q1 t$ |$ K. y0 [</code></pre>
5 o" H  M) K! v  s( G<h4>示例 4:全局钩子 - 拦截 HTTP 请求添加跨域头</h4>
; M' p% v6 ?5 K<p>场景:自定义跨域配置(替代 <code>pb_config.json</code> 中的跨域设置),允许指定域名的跨域请求。</p>* ^( J4 J* z9 D
<p>创建 <code>pb_hooks/app.hooks.js</code>:</p>4 C  ^4 |* ?! [
<pre><code class="language-javascript">// 监听所有 HTTP 请求3 v/ `: _4 R- B; D
onHttpRequest((e) =&gt; {
; l' g5 a. c' @- r6 H" \' z  // 获取请求的 Origin 头
+ a9 r) h9 B$ x+ ~8 d" Z7 D  const origin = e.request.headers.get(&quot;Origin&quot;);" ^: Q3 g6 p5 a9 J) I, A
  // 允许的跨域域名列表! {! c" e9 w2 e8 X' b
  const allowedOrigins = [&quot;https://your-domain.com&quot;, &quot;http://localhost:3000&quot;];
5 F0 i: h/ o6 k4 }- k3 w9 G( b$ I9 H0 C) v6 A* O. k  A5 i: |
  // 若 Origin 在允许列表中,添加跨域头7 q( j1 |. s9 x1 ~/ ]7 w
  if (allowedOrigins.includes(origin)) {/ [+ n# H4 L+ N7 d$ t
    e.response.headers.set(&quot;Access-Control-Allow-Origin&quot;, origin);
8 @2 D' w+ [1 z1 p$ [" x    e.response.headers.set(&quot;Access-Control-Allow-Methods&quot;, &quot;GET, POST, PUT, DELETE, OPTIONS&quot;);( ^$ v" D1 X; ?/ O8 \) G
    e.response.headers.set(&quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type, Authorization&quot;);
" T2 P! V1 G' N  }  }: e: w0 F& _2 n( |
6 J% I/ D& m1 b1 S( R
  // 处理 OPTIONS 预检请求. p2 k' p+ y$ B; ^$ {* v# z
  if (e.request.method === &quot;OPTIONS&quot;) {$ Z. t5 Z, u6 F& f4 n+ b# d
    e.response.status = 204;; K. L! w5 S) z# Y  `; f6 N
    e.response.body = &quot;&quot;;
6 _- D- s- G2 J) O4 }) {3 ]  }- X6 ]9 u) C/ c& J
});
3 W6 O# b* ]) R# R' S7 @</code></pre>
) g$ g% X3 ~1 i/ P* y+ J<h4>示例 5:认证钩子 - 自定义用户登录逻辑</h4>5 A3 S- d2 M+ j
<p>场景:用户登录时,额外校验「账号是否禁用」(<code>users</code> 集合需添加 <code>is_disabled</code> 布尔字段)。</p>  N. U; |1 F1 J0 o
<p>创建 <code>pb_hooks/auth.hooks.js</code>:</p>
- M& i  U' a. @/ F$ h3 ]# }( _; R<pre><code class="language-javascript">// 监听用户密码登录事件: J  u; B' ?7 T
onRecordAuthWithPassword((e) =&gt; {
7 n7 l/ I) D  l  // 仅针对 users 集合的登录
( p% l$ b* I- M- o" c! E" c. E3 x% [  if (e.record.collectionName !== &quot;users&quot;) {
7 ?# }, {! {6 B: X. M4 m8 V$ [" X/ V    return;
! x% T9 I5 K. S  w4 h  }
" y4 e% L1 r6 h7 O( L# k
# Z* K- y+ F( n) d  // 检查用户是否被禁用
1 U! Z1 C- I; X! {  const isDisabled = e.record.get(&quot;is_disabled&quot;);/ |. Q6 H7 l5 P+ K# A, m
  if (isDisabled) {3 v3 A7 Y7 O+ ?9 p% }, d$ B
    throw new Error(&quot;该账号已被禁用,请联系管理员!&quot;); // 终止登录
% j) O6 w- D. n$ J6 B4 w1 Y/ C  }
; u# i, F- G' E0 w
: y  f1 C4 ?# S8 I  // 登录成功后,记录最后登录时间
5 r( z& ^. I; @/ q) p0 s9 f  e.record.set(&quot;last_login_at&quot;, new Date().toISOString());: K: C% S* D6 w+ i8 V; ]5 J" e/ H8 @
  await $app.dao().saveRecord(e.record);8 C& I6 G6 S  S4 n& t1 |6 t- T: j
) W- C# ^6 ^, c$ b4 W- c: M
  console.log(`用户 ${e.record.id} 登录成功,最后登录时间已更新`);+ I/ [: W' k; {* |; ?, z  @+ A+ g# i3 o
});
0 u, e  x8 C+ h2 ^! g: x</code></pre>
( i+ X( Q7 Z- u# K* k) U! }, V' a  r<h3>4. 钩子调试技巧</h3>* @) p* }+ b! ?( w5 }
<ul>
$ m6 e3 R% L2 b8 d<li><strong>日志输出</strong>:使用 <code>console.log(xxx)</code> 输出调试信息,日志会写入 PocketBase 运行日志(堡塔面板「进程守护」→「日志」可查看);</li>
4 k: ?% N5 e8 U" w0 z+ @% `<li><strong>错误排查</strong>:钩子脚本语法错误会导致 PocketBase 启动失败,可在终端手动运行 <code>./pocketbase serve</code> 查看具体错误信息;</li>
' g/ A1 ^! g; V<li><strong>参数打印</strong>:触发钩子时,打印事件对象 <code>e</code> 查看可用参数(如 <code>console.log(JSON.stringify(e.record))</code>)。</li>
$ B$ I0 \% U. r+ C* c( Q9 A</ul># u' l( b& M" S% r4 M; ~( q
<h2>四、总结</h2>
3 Y6 a; E7 G8 x( X, _2 L8 b' E<ol>2 Z+ N! {( q$ m7 E; d5 n6 b
<li><strong>保留目录核心要点</strong>:' m% B9 j0 a+ g& b
<ul>
; `& ?! L6 q9 C+ }9 D+ u5 b' R<li><code>pb_data/</code> 是核心数据仓,备份该目录即可恢复所有数据;</li>
) w1 Z$ e" b! \1 p. H<li><code>pb_hooks/</code> 存放自定义钩子脚本,启动时自动加载;</li>& |2 o( f0 `' X: F8 U
<li><code>pb_public/</code> 托管无需认证的静态文件,<code>pb_migrations/</code> 管理数据库结构变更。</li>
2 W( h" N# \9 d: m* v* Y</ul>
' j- z- m: h- I4 O  K9 D/ N1 v. _/ x</li>
0 ?1 y/ c/ C$ Y8 Y$ r$ r) A! q; a  X<li><strong>钩子使用核心要点</strong>:4 h3 v% u& g- d8 a
<ul>* z. _  i# r+ F9 j6 r
<li>钩子分「集合钩子」(针对数据操作)和「全局钩子」(针对系统事件),放在 <code>pb_hooks/</code> 目录自动加载;</li>7 q9 S# h! ?) J/ r: [+ Z, B9 x
<li>常用钩子:<code>onRecordBeforeCreate</code>(数据校验)、<code>onRecordAfterUpdate</code>(日志记录)、<code>onHttpRequest</code>(跨域配置);</li>
; a( s3 Z9 b) x# N1 O' P; b; ]( t<li>钩子中抛出错误会终止原操作,适合做数据校验;可通过 <code>$app.dao()</code> 操作数据库(如创建/更新记录)。</li>
. a& t5 H3 S# T' Z8 n</ul>
  j- q  L. ]. q# I" P4 G$ Q</li>$ _+ j# ?6 t" W( R" w
<li><strong>实战建议</strong>:
' S* q; E2 X2 q<ul>
2 _# I; p0 J; A" `/ D<li>钩子脚本优先实现核心业务逻辑(校验、自动填充),避免复杂计算;</li>0 _; e" T3 A5 O; v1 I7 A8 w
<li>修改钩子后需重启 PocketBase 才能生效;</li>
7 [' u( v. v$ k, ~, x& `$ h<li>生产环境需备份 <code>pb_hooks/</code> 目录,避免钩子脚本丢失。</li>
8 C' x% R! O5 v$ ]5 O  `, K, ?1 M: |</ul>
; g, E6 A: @& o1 F; {</li>2 e- |5 n( p1 M/ \
</ol>3 P9 X' ~% a6 Y* y( F
[!luckypost!]: digger 被钱袋砸中进医院,看病花了 1 匠币. !lucky_goodrank! / !lucky_badrank!
匠心独运,千锤百炼,品质非凡。
回复

使用道具 举报

打工日常 发表于 2026-1-4 13:00:20 | 查看全部 来自:Error
<h1>Debian 12 下 PocketBase 全维度配置指南</h1>
, ^  f6 W2 y! T# g: C( b" `" T<h2>一、核心需求确认</h2>
9 ?4 j, k$ P1 s0 z<p>你需要在 Debian 12 系统中完成 PocketBase 的<strong>全场景配置</strong>,包括基础网络(端口、绑定地址)、邮件(SMTP)、存储(本地/S3)、安全(跨域、认证)、应用基础(日志、时区)等核心配置,同时掌握配置的生效方式、备份与问题排查方法,适配生产环境的实际需求。</p>
$ k( P0 D* x$ z" ?+ {<h2>二、PocketBase 配置的核心入口(Debian 12 环境)</h2>( k0 b& {, z; |
<p>PocketBase 的配置主要通过 4 种方式实现(优先级:命令行参数 &gt; 管理后台 &gt; 配置文件 &gt; 钩子脚本),所有配置最终会落地到 <code>pb_data/pb_config.json</code>(运行后自动生成),以下是各入口的适用场景:</p># [& O0 Q% q/ n, A4 P
<table>" r( Q: b8 d! b
<thead>
; O1 q7 H8 _, s5 @1 o<tr>
+ Q1 g& G' A* M+ A9 G<th>配置方式</th>
% T; ]5 s" P5 Z<th>操作路径</th>
5 X( q# D/ B6 _1 V* g9 m; a/ T8 x; e<th>适用场景</th>0 t9 h9 X' d3 J8 j
</tr>
& a$ |8 Q4 Z6 _2 }' U# Z</thead>! f3 E' J+ g" `9 c, N
<tbody>9 }9 b/ _7 g6 S; j
<tr>4 {% B4 ?) O. b- ~% f0 e1 q/ V
<td>配置文件</td>
6 m- ?1 k" E# @7 y<td><code>/opt/pocketbase/pb_data/pb_config.json</code>(手动编辑)</td>$ X& k* }, ~8 T3 V. V0 F2 g: I& D; }
<td>所有基础配置(网络、邮件、存储、安全)</td>
7 x1 d* P# g1 a  i4 q! }" P</tr>  j1 z+ ^$ u% U: y0 L3 G
<tr>
% f" D: {, H' k9 M* h. P4 K<td>命令行启动参数</td>
, x' v# l0 V0 o) k<td>启动时追加参数(如 <code>./pocketbase serve --http=0.0.0.0:8080</code>)</td>3 d' _1 `! Q6 Y& X. H
<td>临时覆盖配置(如测试端口、调试模式)</td>4 n' j1 p& O- n
</tr>9 [* b7 V; k$ S5 C& n; U
<tr>
& o# _6 a6 K) |2 D<td>管理后台</td>
' C2 C* _$ Y& j<td><code>http://域名/_/</code> → 设置(Settings)</td>5 l. g# z# B- m! p3 n: j* a
<td>可视化配置(邮件、跨域、认证策略)</td>
; R( }+ B8 t+ Z9 l/ h7 T2 y</tr>/ f6 _6 u. O  ~" }
<tr># z& f" V! g" l
<td>钩子脚本</td>
2 M" F  ^% t2 W<td><code>pb_hooks/</code> 下的 JS 脚本</td>$ }$ Z+ r) L6 L
<td>自定义配置(如动态跨域、自定义认证规则)</td>
6 e. \" l9 ?- {( B4 S</tr>7 w( _3 e; ?+ d% D
</tbody>
( f0 n0 S0 a2 a6 f</table>
# Z& L- k' \/ g, L<h3>前置操作(Debian 12)</h3>( n# E9 J. a/ A- f- Z! O7 `
<ol>0 c; _+ `, Z' n6 O9 a& [5 B
<li>确认 PocketBase 工作目录(默认 <code>/opt/pocketbase</code>),若路径不同需替换下文所有路径;</li>0 M& {1 w6 ?4 [) l6 J1 P8 H' m) m2 A
<li>确保对 <code>pb_data/</code> 目录有读写权限:
# |7 [; P/ u& }( a/ a7 v( A! L<pre><code class="language-bash">sudo chmod -R 755 /opt/pocketbase/pb_data  E# ]+ j5 u" _, [  s! B0 ]! g
sudo chown -R root:root /opt/pocketbase/pb_data  # 或你的运行用户5 l. v5 [1 [; V' H+ B: k* G
</code></pre>
, P) _3 `) Z( h/ d/ ~: V) D, |  Z3 Y</li>' u! m6 {2 ~" o; m. R8 H7 m
</ol>
% p. e" l) N( l/ p" @3 R( A- C5 x<h2>三、核心配置模块(Debian 12 实操)</h2>
( {# }- Q- N0 Z! G<h3>1. 基础网络配置(端口、绑定地址、HTTPS)</h3>; O, O/ `5 K9 m0 V% Q
<h4>1.1 修改默认端口/绑定地址(3种方式)</h4>; u1 W7 x2 r" ?) G- U
<p>PocketBase 默认监听 <code>0.0.0.0:8090</code>,以下是修改方式:</p>
  h* o5 R4 p! J, o, G7 N) |4 }<h5>方式1:命令行参数(临时生效,重启后失效)</h5>
8 w! q! V* ~* x: g& y<pre><code class="language-bash"># 切换到 PocketBase 目录  @# o3 i: D9 ]4 a  b
cd /opt/pocketbase
6 C* U  G8 V( f# n5 q% h/ \  H/ z) P4 a, c* U/ U% D
# 监听 8080 端口,仅绑定本地回环地址(仅服务器内部访问)
7 o9 {5 E, W. s) P1 y./pocketbase serve --http=127.0.0.1:8080
. J$ A% O" J8 _# p% O5 h! `5 c4 w% ~. m+ F  w: `* u
# 监听 80 端口(需 root 权限),绑定所有网卡+ |4 Q4 d; j% O: X
sudo ./pocketbase serve --http=0.0.0.0:80; D4 M4 K" B2 Y) t. q
</code></pre>
. k. F  h) u; T+ N8 V! ^7 D<h5>方式2:配置文件(永久生效)</h5>  x8 C8 K' v9 r. d+ C
<ol>1 Q6 U6 ?2 ?7 p) _& g3 O) j
<li>编辑配置文件:" z* G( D- ^- H/ w  W! K
<pre><code class="language-bash">nano /opt/pocketbase/pb_data/pb_config.json6 b7 j7 p7 x+ _( Y1 Q2 I7 g- M5 ^
</code></pre>
8 @* a& W7 u/ t1 U1 e0 D</li>
: n8 i% w7 {: v' w8 v8 M<li>添加/修改 <code>api</code> 节点(无则新增):* w; J- i# c. y3 O. B
<pre><code class="language-json">{
8 R& V8 B* h) G3 h+ Y; y  &quot;api&quot;: {
# @+ U' }% }. K9 \+ g5 B    &quot;httpAddr&quot;: &quot;0.0.0.0:8080&quot;,  // 绑定地址+端口
% u* }, ?/ \9 W" E    &quot;httpTimeout&quot;: 30           // 请求超时时间(秒)4 K( l8 R& }0 V( ^: h& f0 Q8 f
  }
6 {- m8 @' F$ G8 @' X}
: @" N4 y* K( o7 }+ {</code></pre>) H* _7 {  D8 Y4 c
</li>, W9 Q4 C) f. A4 v/ E. s# L3 ]. z
<li>保存后重启 PocketBase:) U2 \( K; M0 `$ X( F0 O9 Q. o
<pre><code class="language-bash"># systemd 服务方式: ?1 q7 k! j) |
sudo systemctl restart pocketbase
- Z2 B4 N- w2 I, z+ V5 Y0 A1 R/ j! h1 B9 G1 L0 X$ B
# 堡塔面板方式:进程守护 → 重启 PocketBase. a, ^6 m  h! d0 V7 U- [9 L
</code></pre>7 w% I" E' [9 r3 {1 V7 B
</li>- }% ?* T( L2 C3 ]; }2 _, Q
</ol>
# D7 j5 p% J& ], x<h5>方式3:堡塔面板进程守护(永久生效)</h5>  v' Y9 W6 B; g5 r1 ~& T" g0 y, }
<ol>
' @( k! _* l+ d% d  T<li>登录堡塔面板 → 进程守护 → 找到 PocketBase 进程 → 编辑;</li>
% U* \0 f3 b- ^8 O8 y1 X( ~<li>修改「启动命令」为:
* n- |! M# Q$ y<pre><code class="language-bash">./pocketbase serve --http=0.0.0.0:8080
9 l% u, j8 p0 f' }* M9 h# Z8 _</code></pre>$ a$ ?. O8 F6 W0 l2 V4 [
</li>5 ^2 }6 [/ w' w. a+ g# [4 f3 ^
<li>保存并重启进程。</li>
$ \* Q/ L9 G$ L/ D</ol>
0 r1 u; P1 m% T- P% }1 p9 r<h4>1.2 配置 HTTPS(Debian 12 推荐 Nginx 反向代理)</h4>/ j" e4 ?0 V, H6 b
<p>PocketBase 自身不直接支持 HTTPS,Debian 12 下推荐通过 Nginx 配置(替代 PocketBase 内置的 HTTPS 方式,更稳定):</p>5 P) e8 k. A+ V4 F2 ^2 ]3 e
<ol>
; }- U/ w+ X3 s6 M<li>安装 Nginx(Debian 12):
! u. H, T1 D! h8 n; ?& R0 k/ f! P<pre><code class="language-bash">sudo apt install nginx -y+ B( H) i. t; c9 [0 k) U) \9 a" {" \6 O0 I
</code></pre>" I: [- n0 ]: c* u9 P! B" t
</li>
2 e5 {& I( ~2 k+ ^6 R<li>创建 Nginx 配置文件:
$ V' e6 e* x( E6 F<pre><code class="language-bash">sudo nano /etc/nginx/sites-available/pocketbase-https
/ w* u9 o. [" C+ E. ^: N</code></pre>3 b# u/ B* o; {, N
</li>) J7 o1 r3 Q" l; K/ Z
<li>粘贴以下配置(替换 <code>your-domain.com</code> 为你的域名):, _3 x: D& J; W% m
<pre><code class="language-nginx">server {. K/ ~/ b2 ^, L9 {& y, \
    listen 80;4 K7 Z0 d1 j9 K6 l: B
    server_name your-domain.com;
' U0 d/ V  j9 b* I9 V; g" P    # 重定向 HTTP 到 HTTPS$ V$ A) \! V  a. W- i
    return 301 https://$host$request_uri;- [" A+ Y9 x4 C4 e
}' ~$ V  ?' `' D1 l7 p5 e. C$ |

0 J. A2 y  z4 c3 X! Tserver {  A1 g! U2 ?* H* Z# L& i
    listen 443 ssl http2;
5 e9 h" y! G8 `0 Q    server_name your-domain.com;/ s, n1 E9 f9 C
0 C- L7 p& `7 A) K6 m
    # SSL 证书(Let's Encrypt 免费证书)
4 E" J3 y5 L. g; }) l2 a    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
4 L/ O4 A2 L/ q4 U6 o9 X    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
3 k5 Y. d* _9 {5 `3 [: ^( @0 r+ z( h    ssl_protocols TLSv1.2 TLSv1.3;% l+ T1 q3 s1 e7 ]% n5 D; f" ]

% l, [% \$ R  V7 J6 J    # 反向代理到 PocketBase7 O7 g; W: u6 j
    location / {7 V$ _! q' Q$ H/ E! x
        proxy_pass http://127.0.0.1:8090;1 |# Q' j& D' L& l
        proxy_set_header Host $host;
0 |* a( F" E& }4 O, E  W, {        proxy_set_header X-Real-IP $remote_addr;
( `0 g* s) E7 d; G( T8 r; v        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
3 [3 f1 D9 [" D! a        proxy_set_header X-Forwarded-Proto $scheme;
6 O+ ]  m5 q; O- X& S  Q3 X  o( h9 }    }) C# s2 M2 c4 L" u1 z$ W7 s
}  m# H- u5 O4 d1 H; r; y
</code></pre>
$ k% ~, z, J; f) N* D</li>+ D& _/ z6 P/ B) ?3 ?! U
<li>启用配置并重启 Nginx:
" R7 f2 u! p9 l' n0 e4 h<pre><code class="language-bash">sudo ln -s /etc/nginx/sites-available/pocketbase-https /etc/nginx/sites-enabled/7 e, q! M" g  s- ]; ?
sudo nginx -t  # 校验配置语法! R/ l6 }/ H, X* @
sudo systemctl restart nginx0 g! X6 j' Q$ y- a0 O. D" f
</code></pre>  S7 {0 N6 z3 T+ ?. R
</li>. W: b& m& U7 [
<li>申请 Let's Encrypt 证书(Debian 12):
; T3 ^, y0 @$ }: k+ F) k<pre><code class="language-bash">sudo apt install certbot python3-certbot-nginx -y
+ m# |+ Y; \  f* |" Osudo certbot --nginx -d your-domain.com
- E; d1 s" S* g$ c</code></pre>' b" k9 h0 m! j- `. o
</li>- a( V/ S0 d' H4 R& R( s- H$ W
</ol>& {4 W' p$ s9 v  K2 z0 V# t- Y
<h3>2. 邮件配置(SMTP,用于密码重置/验证)</h3>
5 T: W3 z/ y0 e4 J; u% f: C<p>PocketBase 需配置 SMTP 才能发送邮件(如用户注册验证、密码重置),以下是 Debian 12 下的配置步骤:</p>
- H6 ]& s% g- m3 n* ^" v3 K<h4>方式1:管理后台可视化配置(推荐)</h4>1 J. L; S2 A2 n! c
<ol>3 u9 b  ?0 N* J3 |" h2 C( R$ j
<li>( U' F% d( {. ?0 ?  C% {7 _
<p>访问 <code>http://域名/_/</code> → 左侧「Settings」→「Mailer」;</p>: \/ M5 G* {- y2 N
</li>( b' i$ A6 }, I3 K) B( ^
<li>1 X* a. q4 ]6 P4 m
<p>填写 SMTP 信息(以腾讯企业邮/QQ 邮箱为例):</p>+ L2 ^; Y" `5 `! d8 ^0 e5 w& u
<table>3 @( t5 r! @: u- {3 E
<thead>8 B' z; q- u# J# j5 P
<tr>" n% l5 O$ ]& p
<th>配置项</th>
/ k& V9 D/ z, b- W9 p<th>填写内容(QQ 邮箱)</th>
/ e1 ]5 U' F0 j- k) o* B3 `8 s4 c</tr>2 a( o: W  r9 f' z. `& ~
</thead>
, A- s* N( f' B( n/ `<tbody>* l  W4 k: p* W0 ?" F5 m+ s7 x! W8 ?
<tr>
1 j2 l" x8 P% ^" _, G. j- G<td>From address</td>
" I$ i2 X& o) h' \<td>你的邮箱(如 <code>xxx@qq.com</code>)</td>$ \) {! b2 p: Z5 F' I9 v" F4 P- U/ ]+ j
</tr>
0 [+ C0 v. X/ a' j; S  {# r<tr>* K* e6 ]- |) k& M, j) ~5 b
<td>From name</td>
& ~! u" R# ^) V$ z. l<td>PocketBase 应用(自定义)</td>" s5 L* D( j0 Y
</tr>
8 c5 S# Y3 b0 e<tr>
4 V5 a- a) }. H" g<td>SMTP host</td>6 ~0 e+ T# b* d9 B0 K8 N
<td>smtp.qq.com</td>
. }: D, ^4 A5 {$ |: f</tr>1 b1 i0 L$ s8 a0 p# z+ w
<tr>! [) d* @% v, K) {. G3 x+ h" m
<td>SMTP port</td>
5 c3 B4 D! _/ J1 N* ~! d<td>465(SSL)/587(TLS)</td>, q( V% v* n7 C. S
</tr>4 w7 s% M, w8 ^9 K+ W
<tr>. p7 i& r, F% a- j
<td>SMTP username</td>
- x, ^# X8 o) ]' P- l<td>你的邮箱(如 <code>xxx@qq.com</code>)</td>, n# N' P5 }) c& F5 M
</tr>6 V, `% k7 Q4 E4 M1 ~4 O/ b7 I( Z! g
<tr>
/ N8 s2 V: j  X' ?/ u<td>SMTP password</td>3 m0 t# U  i4 g; _! D" K
<td>邮箱授权码(非登录密码)</td>
) |3 a" V3 D. L! c: S6 z</tr>3 E  \! N$ Q- v" c! P
<tr>
- R& G/ Y9 [1 ]' N9 f" ]8 C* x<td>SMTP secure</td>
4 w6 y& p  C/ N<td>SSL(对应 465 端口)/TLS(对应 587 端口)</td>9 j& u! h+ i5 `1 p
</tr>
" J+ }3 G8 e  M$ ?: Z) q6 H* J</tbody>) \+ @8 Z2 R5 Z* P4 c4 @0 [" O
</table>
. F$ C! v& D. n7 ^; X7 {' H</li>
4 e7 K' R' A1 J0 n( Z<li>
5 `1 v* V. C- R. F( O/ t) E<p>点击「Test」测试邮件发送,成功后点击「Save」保存。</p>
& p9 |6 C' S/ G' p+ V( E9 W, o</li>1 R- u0 o8 B& b$ U
</ol>
4 k. q. J+ K2 I- q+ l<h4>方式2:手动编辑配置文件(永久生效)</h4>6 n% |. E" g' J: C, ]( i( g
<ol>+ [! G5 g0 g/ L  E- d* [3 L
<li>编辑 <code>pb_config.json</code>:& `6 v! {1 T7 k+ h, T: i" M; f2 f
<pre><code class="language-bash">nano /opt/pocketbase/pb_data/pb_config.json
3 u: X2 S0 ~" _2 @" J, v8 @</code></pre>2 ~5 B, |. d+ Z
</li>8 o& h1 R* ?4 Z& i' X
<li>添加/修改 <code>mailer</code> 节点:
, n) X5 h' b2 Y/ ~. @7 T  x<pre><code class="language-json">{
8 q, u& Y6 j- C3 j. K  &quot;mailer&quot;: {
, D6 O% E; Y" O( l    &quot;fromAddress&quot;: &quot;xxx@qq.com&quot;,
1 |4 W, i0 j9 L1 M* M    &quot;fromName&quot;: &quot;PocketBase 应用&quot;,
+ r; n. N0 X; G    &quot;smtp&quot;: {: D& E% x( f& |: T9 y) d& V- @5 \. _
      &quot;host&quot;: &quot;smtp.qq.com&quot;,- t* }: b8 u- o9 w/ y# K  v3 C
      &quot;port&quot;: 465,# Y' M2 r0 i) W
      &quot;username&quot;: &quot;xxx@qq.com&quot;,  ]3 o$ v- |, N& b) m; E
      &quot;password&quot;: &quot;你的邮箱授权码&quot;,
6 e9 `- {- \, [( L      &quot;secure&quot;: true  // true=SSL,false=TLS1 g  K3 N4 ?1 }- n* ~
    }3 h1 K- \; R$ c+ x7 P0 q, A
  }+ }2 G9 ^5 I2 U% |, U$ w
}( W0 z1 y6 D  U5 ?
</code></pre>. E! D  i+ ~8 X  ]0 g
</li>
6 A/ I. @' h( F- Q% M<li>重启 PocketBase 生效。</li>+ ?* w& ?$ L, L( X' v7 [
</ol>
* ?, p1 b2 }2 Z3 m4 i3 `  m: n4 p0 Y<h3>3. 存储配置(本地/S3 兼容存储)</h3>
, I+ \3 W( X  v<p>PocketBase 默认将上传文件存储在 <code>pb_data/storage/</code>,可配置为 S3 兼容存储(如阿里云 OSS、腾讯云 COS)。</p>' d! d* k) R* w# b; B& c
<h4>3.1 本地存储配置(默认,调整路径)</h4>
) }9 B! `9 s$ N) s  [<ol>
5 E, R  f! u. I<li>编辑 <code>pb_config.json</code>:3 @0 z0 W& s) G( B! M$ ~9 c1 l
<pre><code class="language-bash">nano /opt/pocketbase/pb_data/pb_config.json+ |, n- R) U; \6 |! _# [3 U% E8 h
</code></pre>6 i  B8 T2 [; `: M# I5 B
</li>
  t, H6 G* A$ P5 p5 N7 D<li>修改 <code>storage</code> 节点(自定义本地存储路径):
7 a& l) O, h$ X+ e5 a<pre><code class="language-json">{: E. N! G, Y( s  P1 ]% v9 _' {7 T+ }
  &quot;storage&quot;: {
; y; C+ x; Q+ N- ?( I4 K1 j% f    &quot;local&quot;: {7 k1 R- H6 q' M! Y/ T" r% a
      &quot;path&quot;: &quot;/data/pocketbase/storage&quot;  // 自定义存储路径(Debian 12 需提前创建)) H) M3 G3 P% L$ J
    },
6 L8 N  ?, G2 q$ z- t    &quot;active&quot;: &quot;local&quot;  // 启用本地存储
( x0 }, B  `7 j2 G5 e  }+ d/ d& j5 q% d" g! v4 t9 c9 y; x+ w
}
) I# _1 r; c' h! z</code></pre>2 V! i; Y0 e. `! q1 z" @
</li>
7 V  h! w$ [! c% r. i. ~' D<li>创建自定义路径并授权:
+ g0 h/ N8 n+ W2 ]" F& n<pre><code class="language-bash">sudo mkdir -p /data/pocketbase/storage
6 a( j, q7 |5 t* Wsudo chmod -R 755 /data/pocketbase/storage% b. ~; [3 D% Q* N2 K5 Q
sudo chown -R root:root /data/pocketbase/storage: ?% u$ L( k* D, s
</code></pre>
; R+ e  |, T/ Y* X& j</li>
) t4 r: V, q, w+ z<li>重启 PocketBase 生效。</li>- y/ O" \) D& m
</ol>+ ~1 {1 V$ }& t
<h4>3.2 S3 兼容存储配置(阿里云 OSS 示例)</h4>  l7 T2 w" k# `: [; ^: b$ [, L/ U
<ol>
! ~+ H# M$ y# Z1 l' C<li>编辑 <code>pb_config.json</code>:
& R! ?# h- F, P<pre><code class="language-json">{
0 u$ x( K  m7 U7 H  &quot;storage&quot;: {3 \+ l' @4 u  n& I
    &quot;s3&quot;: {+ M1 d9 l5 M3 c' ]+ n, O7 Y+ ~2 j
      &quot;accessKeyID&quot;: &quot;你的阿里云 AccessKey ID&quot;,
0 v; Y0 N( ?$ {8 N! p/ ~      &quot;secretAccessKey&quot;: &quot;你的阿里云 AccessKey Secret&quot;,) _6 r$ |+ J/ N3 g0 p8 r; ^& N
      &quot;region&quot;: &quot;oss-cn-beijing&quot;,  // 阿里云 OSS 地域2 z1 c7 E$ ^% j; |3 @* p* r  t
      &quot;bucket&quot;: &quot;your-bucket-name&quot;,  // OSS 桶名称! e+ J; C$ A  o, d) X/ ]
      &quot;endpoint&quot;: &quot;oss-cn-beijing.aliyuncs.com&quot;,  // OSS 端点0 e4 R( \$ U8 O& Q
      &quot;disableSSL&quot;: false,
6 Q5 s4 d; M& P5 M5 s% h      &quot;forcePathStyle&quot;: false
$ l2 W5 i4 o- X2 N) o3 ]    },
2 U, t, v+ {7 ^7 f    &quot;active&quot;: &quot;s3&quot;  // 启用 S3 存储9 O3 F* i# x  U; T
  }
2 Q$ Z4 u  [/ P7 |" ~2 R! U}8 F+ b/ `+ }1 G* k0 \: h: H
</code></pre>
, ?" n# Y7 {/ e6 [, f</li>; v' m; y; D5 F
<li>重启 PocketBase 生效,上传文件会自动存储到 OSS 桶。</li>& i0 g" h! j7 i; a/ d& c1 s
</ol>
: j1 U$ D" }( D<h3>4. 安全配置(跨域、认证、密码策略)</h3>! y* }5 p  a+ ?, S" T) Y: \- ^
<h4>4.1 跨域配置(CORS)</h4>
! E) `; [! O' O# P& ^! d9 k<h5>方式1:管理后台配置</h5>0 i4 H- X" W& t' o& Y2 P- P
<ol>
# L$ |& O6 E2 H! O, m/ S5 ~3 H<li>访问 <code>http://域名/_/</code> →「Settings」→「API」;</li>
, A2 r  N. @5 p* j: `- F& b8 ?& e<li>在「Allowed origins」中填写允许的跨域域名(如 <code>https://your-domain.com,http://localhost:3000</code>),多个域名用逗号分隔;</li>" d: x+ j! C& G5 x8 [0 A% A
<li>可选:开启「Allow credentials」(允许携带 Cookie/Token);</li>/ t3 W6 ?+ a( s# A6 B
<li>保存后立即生效(无需重启)。</li>
4 A# R9 r* {0 L</ol>, \% w2 f  V' D9 Y
<h5>方式2:配置文件配置</h5>3 |+ U3 `+ v0 P, @2 T/ Y
<ol>
: k" k, \2 {3 c/ s<li>编辑 <code>pb_config.json</code>:/ h& Q7 ~0 ^6 n5 U3 B; O* U
<pre><code class="language-json">{
, e# G5 R- [% s1 d8 M& i0 u  P  &quot;api&quot;: {
( m6 w+ P/ F- `8 O+ u4 T& W7 x  F    &quot;allowedOrigins&quot;: [&quot;https://your-domain.com&quot;, &quot;http://localhost:3000&quot;],
4 k: O" a( l; I1 O6 P    &quot;allowCredentials&quot;: true% n$ r$ v3 G. o; Y
  }0 t% F3 c8 K# C! ]* O* j
}
" g6 y( H* @( @$ f0 |! I</code></pre>
$ S8 _2 c) p) C8 m</li>
) }5 ^. P' |  G5 |! K<li>重启 PocketBase 生效。</li># F! b) e, ]) q- J* ?1 |2 P' R
</ol>
: ]3 y" r* B( j; A* o<h4>4.2 认证安全配置(Token 超时、密码策略)</h4>* ^* B1 I7 @/ O# m* f) A5 ~- F
<ol>: \6 d) e" f& t  D& L- m5 e
<li>% c, {0 Q% a5 ?- F0 m9 A, p( S
<p>管理后台配置路径:<code>Settings</code> →「Auth」;</p>; F5 C( e7 V9 n- c; G8 c; u2 u
</li>
* b# l1 v1 ]* s: P/ I0 C9 g* a<li>
7 F! G8 `9 p- L4 X+ A4 S<p>核心配置项:</p>
' E9 c  {, J! x2 n& g<table>
# N# K; W/ _& ^% S<thead>  L" u% v' a  [; |6 p  a! A+ y
<tr>! z, @6 P) x3 L
<th>配置项</th>
/ E8 Z% e# R$ \/ t1 t<th>作用</th>( l. }  \' U4 D& z/ a$ Q4 Z
</tr>
4 E) k8 v' V! F9 O</thead>$ k9 `6 h2 N# F- M' u6 Z# V
<tbody>
% E7 V7 H" W6 A$ P& h* Q<tr>
& B9 |4 o& h* m' _7 w<td>Token duration</td>1 z% _# a& l2 O* E
<td>用户 Token 有效期(如 7d=7 天,1h=1 小时)</td>
; Q# r! D9 ]. ~% v5 ?* s, B</tr>% |4 s; w; N! W7 |
<tr>2 V! j) f2 K1 K* v
<td>Password min length</td>" V8 ?( n7 S7 s% p" h& X9 q5 i. V
<td>用户密码最小长度(推荐 ≥8)</td>
( g+ [1 P+ S5 D2 }5 V, P7 l</tr>8 ]% s& W3 G  J
<tr>
/ |2 C( G# Q' V<td>Password require chars</td>% \5 m' @8 g8 v7 t
<td>密码复杂度(是否要求大小写、数字、特殊字符)</td>% W7 p! G4 f: Q
</tr>
9 l4 j5 P6 D8 T. w' i- r<tr>
# b  Q9 D' g) Q, ~/ k4 a/ s<td>Max failed attempts</td>. n% k( \" G# X* s- e! v9 n" O9 a
<td>登录失败最大次数(超过后锁定账号)</td>
4 j( a3 Y' C; c3 I' Z. h</tr>
  p% W0 ~; j: w9 T</tbody>" x- t6 l; ]0 J) u
</table>
$ r! Q2 M5 E8 Q* s3 F6 d( L- L! E</li>* w. F9 ?/ G, T8 [  i
<li>
9 T% h7 y4 c' F" P" c9 P- \, T  f<p>保存后立即生效。</p>/ m. i; h, B0 ~& I! Q- B. r# K
</li>  T4 }# ~1 E6 V
</ol>2 `0 b1 x! L! @; s
<h4>4.3 管理后台安全配置</h4>/ M. b2 J7 b5 a+ O
<ol>1 B# J$ @8 d9 g' s
<li>限制管理后台访问 IP(Debian 12 防火墙):
" N6 K# {6 p* y# l; z6 N4 w<pre><code class="language-bash"># 仅允许 192.168.1.100 访问 8090 端口(管理后台)3 i9 v7 A* d: X1 o4 E
sudo ufw allow from 192.168.1.100 to any port 8090
! L2 p7 E5 k6 Hsudo ufw reload
$ r1 [0 h4 P/ w5 p' X2 ]6 \</code></pre>
( ?) G( L% e7 w$ u5 x1 ?* h</li>& x1 q8 T8 @9 z$ ]& c7 o
<li>或通过钩子拦截(推荐,见前文请求拦截示例)。</li>1 B1 C4 ]9 W5 t. E5 u8 E. T
</ol>" j: ~# i$ s) e5 l
<h3>5. 应用基础配置(名称、日志、时区)</h3>. ^2 l9 o4 _1 |4 @) B! z
<h4>5.1 应用名称/描述配置</h4>
7 m* q2 E& i4 ~5 U2 x<ol>
7 [5 ^& `! ~( C2 N  r<li>编辑 <code>pb_config.json</code>:$ S: s: W. S7 M& k# _- G6 w
<pre><code class="language-json">{
: ?9 c' N# M. _( ]( N/ `' Z: _  &quot;app&quot;: {, A# I& ]6 |' Y3 s) w
    &quot;name&quot;: &quot;我的 PocketBase 应用&quot;,+ V0 X. S- L* w& p; F; [( g3 f2 ^1 m
    &quot;url&quot;: &quot;https://your-domain.com&quot;,
/ l' z0 h0 H3 Y5 [0 X* A    &quot;description&quot;: &quot;基于 PocketBase 的后端服务&quot;. t+ L* S) V4 ?% F
  }9 q! u/ X( }- G
}
- a  N) }1 G% f" p. m</code></pre>  n5 g5 j0 Y  J+ {
</li>
6 s. K: |, o" x* \* B<li>重启生效。</li>& x6 C) T- l1 N8 \! n6 b
</ol>
: |* z) I6 u$ o' z; N<h4>5.2 日志配置(Debian 12 持久化日志)</h4>+ @2 Q# [# w; ^* M, C- z$ L
<ol>4 B, w8 F- t: |0 T) _& t1 s& n
<li>编辑 <code>pb_config.json</code>:, w( f1 G& K# b# ~0 W1 R
<pre><code class="language-json">{8 T( T* M! k, l3 G
  &quot;logs&quot;: {9 P5 I7 y+ n3 \3 E" M: D0 |
    &quot;level&quot;: &quot;info&quot;,  // 日志级别:debug/info/warn/error
8 K5 w, l) B  q6 q; ?0 w" ~    &quot;file&quot;: &quot;/var/log/pocketbase/pb.log&quot;  // 日志文件路径(Debian 12)
5 H! D# ~2 [& U  }
# E$ w$ N: l  Z; f7 ?- A}
( B' j* H3 d* P% m; `1 p/ d8 s</code></pre>
$ F/ j7 L' ?; H2 x; p</li>8 ?& s  @' O& e# J' g* l5 v
<li>创建日志目录并授权:
# B9 q$ p5 |& ^8 k2 v. H! |/ L- z<pre><code class="language-bash">sudo mkdir -p /var/log/pocketbase
' P9 f0 d8 E  \4 L7 Fsudo chmod -R 755 /var/log/pocketbase7 C& \- G* p* S2 L, l7 A
sudo chown -R root:root /var/log/pocketbase: r8 g( V# a  ]- T
</code></pre>1 k7 e2 u. g6 n
</li>
" B% w& Q1 {$ m7 F<li>重启 PocketBase 生效,日志会自动写入 <code>/var/log/pocketbase/pb.log</code>。</li>1 L- _' t( e" I9 h
</ol>
3 e- ?  f$ H  B$ e, w5 a<h4>5.3 时区配置(Debian 12 系统时区同步)</h4>
2 C8 ]; x# e% Z+ S/ j1 p* U4 S<ol>
/ W/ S& x3 M' ]' b" l& I5 q/ E<li>先设置 Debian 12 系统时区:
6 u$ B. v5 u) `2 o7 G1 K7 y<pre><code class="language-bash">sudo timedatectl set-timezone Asia/Shanghai2 X2 E: S. ?: P5 L# g& @) H& @( z
</code></pre>
1 e/ ^) b! B; w: B  V0 C( C7 ^</li>8 m3 a& M; [3 s0 g# l" J% N
<li>PocketBase 会自动同步系统时区,无需额外配置;若需手动指定,可通过启动参数:
6 ~' u, F$ ~( q2 }; G) ?; s  {<pre><code class="language-bash">./pocketbase serve --timezone=Asia/Shanghai* p$ w  D" G4 |$ o$ V" |" p4 W
</code></pre>6 O. O8 s' T) c! i
</li>
4 N( `2 p/ a  z$ g0 r: j</ol>3 g" u5 `7 a; w4 h4 T# w5 ^
<h3>6. 自定义配置(钩子脚本补充)</h3>
* U" i* m" g; c7 g1 q5 A<p>对于配置文件无法实现的自定义需求,通过 <code>pb_hooks/</code> 脚本补充:</p>  K& w) W: `) m  a; B
<h4>示例:动态跨域配置(根据请求域名放行)</h4>6 V- y. N. i$ I) l! c: m
<pre><code class="language-javascript">// pb_hooks/cors.hooks.js
7 g3 l  I/ S( n* `6 HonHttpRequest((e) =&gt; {
: f( s+ y3 o0 g6 S# K5 ^6 h  // 动态允许所有子域名跨域, }7 a! }6 A. Q% X
  const origin = e.request.headers.get(&quot;Origin&quot;);
! T" N. H( W( q( e# c! k% i  if (origin &amp;&amp; origin.endsWith(&quot;.your-domain.com&quot;)) {
9 ?7 @1 l' a) h( j0 \& B. r    e.response.headers.set(&quot;Access-Control-Allow-Origin&quot;, origin);4 f" v) E' j) O$ O- |
    e.response.headers.set(&quot;Access-Control-Allow-Credentials&quot;, &quot;true&quot;);. v; n7 Q+ `8 \! q9 T9 }" m* U& k
  }
+ O, H( q# o* n& f9 s  e.next();6 p! z0 Z% s0 a0 c) @  W1 ]& V! c9 Q
});8 s1 p% q7 w: o
</code></pre>
" m/ W# h& @2 p4 {9 Z<h2>四、配置的备份、恢复与生效方式</h2>
0 \7 C7 H8 _' n* z& ~6 Z<h3>1. 配置生效方式</h3>/ k" D3 r6 q# n( o
<table>2 s) ~) [- ^- h1 L; e
<thead>/ G% A( y5 Z6 Z6 S' k7 ]
<tr>
+ ^$ e7 S3 H! Y<th>配置类型</th>
7 K& b6 P. I0 ]- J/ J0 M/ v: o1 e; j<th>生效方式</th>
& J, u$ b, n& |4 U' Q+ f' ?7 r</tr>% l& L2 D5 Z4 i0 M/ Q
</thead>- S! g: |* ]- q0 l% d# A& _- ~
<tbody>
' X! [7 E7 N) n1 r  p$ m* @+ s5 H<tr>( N  Q! T4 q, Z3 B
<td>命令行参数</td>% o, V5 {7 t& `8 t. M7 j2 ?) \
<td>启动时立即生效(临时)</td>
* h  O1 `2 ], h# Y  H" f) Y</tr>$ S$ o: B$ I, R  b6 |$ ?; X
<tr>6 n7 d2 C% q0 g6 ]( d$ A1 z6 u
<td>管理后台配置</td>4 U4 t0 v0 ], C# \
<td>保存后立即生效(部分需重启,如邮件)</td>( y: o4 V$ G9 W
</tr>* a) K0 E; L# t! V8 f& }, A
<tr>
1 a! h) O7 A: j; D' x<td>配置文件修改</td>
( a  Y" Q9 f5 U8 R4 k<td>重启 PocketBase 生效</td>
  l+ p8 V/ f' p1 _</tr>
( L% _# R5 P7 F+ p" o1 ]: j<tr>4 @9 g4 K! S% _. s+ x$ c
<td>钩子脚本</td>0 ^  ^$ {. I  {/ P
<td>重启 PocketBase 生效</td>$ Q& S5 k" x5 ~7 ]; b5 ^3 S" h! p
</tr>2 ]* U$ n) e0 }  O7 p9 x
</tbody>% w# I9 T/ d$ p/ I% S
</table>- C! O$ x  A# r( R
<h3>2. 配置备份(Debian 12)</h3>
) h6 C3 S0 r. i; ^/ j* ~<pre><code class="language-bash"># 备份 pb_config.json(核心配置文件)
. C4 p* X& g/ ]/ `7 I% mcp /opt/pocketbase/pb_data/pb_config.json /opt/pocketbase/pb_config.backup.json
9 ]( h) e: n7 {0 P: f
; ]- y+ h* s4 K+ t4 M5 v+ Z6 J! t# 完整备份所有配置+数据(推荐)) a! J% o* |2 Z$ F" Z9 ?
zip -r /opt/pocketbase_backup_$(date +%Y%m%d).zip /opt/pocketbase/pb_data/
, _0 Y! F/ p8 J! X2 w  f5 p$ J' e: \( V</code></pre>1 y- I3 C4 S$ K3 ?
<h3>3. 配置恢复</h3>; c5 ]- u- w$ `  h9 T
<pre><code class="language-bash"># 恢复配置文件
) V" |: L# ?: F9 }; p6 Ecp /opt/pocketbase/pb_config.backup.json /opt/pocketbase/pb_data/pb_config.json2 y# k" |+ M2 Q$ P; R, }5 b' b
  [2 P* Y$ x! Q
# 重启 PocketBase
) Z% M" A/ e+ {$ `& r9 `  qsudo systemctl restart pocketbase- }: o1 D9 _2 b$ F8 v; P0 L2 K6 V
</code></pre>
+ W5 c& I+ E& h* U<h3>4. 常见配置问题排查</h3>' A+ F- |4 ]+ Y  T% B( G8 }
<h4>问题1:配置修改后不生效</h4>
/ {, m& N5 N4 m, W8 ^, j( t" c<ul>
# v3 _' `; M3 W, p1 }$ S$ b<li>检查是否重启 PocketBase;</li>
$ K3 o5 D8 t# l' i" z8 U, r3 M<li>检查配置文件语法(JSON 格式是否正确,可通过 <code>https://jsonlint.com/</code> 校验);</li>
! |: i  ]. o3 o, ^2 q8 X+ q+ @<li>检查配置文件权限(是否可读写)。</li>
5 a; J7 w9 m% S) ~</ul>
; s9 H4 |% h& ?, t, A<h4>问题2:邮件发送失败</h4>
/ C" u# R/ u) K2 q; B( r/ P# x<ul>: w' E, s" ]. i1 i8 ^
<li>检查 SMTP 端口是否开放(Debian 12 防火墙/云服务器安全组);</li>
  y7 t  ~+ X. y<li>验证 SMTP 账号/授权码是否正确;</li>
( Z0 }: W5 W7 t$ e  ?<li>查看 PocketBase 日志:<code>sudo journalctl -u pocketbase -f</code>。</li>
( X1 X$ j! T' [4 ?1 J. _2 ^1 K; u; V</ul>6 t; d) q7 P. D( O1 A& F6 C
<h4>问题3:端口无法访问</h4>( L1 m3 m- c" U" V1 C
<ul>
2 a' Q% L5 h; Y& o3 q7 p3 t7 R# M+ `3 |<li>检查 Debian 12 防火墙:<code>sudo ufw status</code>;</li>. ]# |- y, S7 x( T
<li>检查云服务器安全组是否开放端口;</li>, B/ e/ l$ e! P7 I
<li>检查 PocketBase 绑定地址(是否为 <code>0.0.0.0</code>,而非 <code>127.0.0.1</code>)。</li>
7 v2 r* A; G6 H3 U  [, \" N</ul>% D$ I( v! |  @
<h2>五、总结</h2>
* U5 u  P: l7 E6 \! O" Z% ^* {<ol>
( ]9 S* J/ z0 d& Q( x5 J9 S<li><strong>配置核心入口</strong>:8 S0 V5 W# t. P! t! t2 E( Y0 ?
<ul>8 H" ]! y& h, e. R
<li>基础配置(网络、邮件、存储)优先通过 <code>pb_config.json</code> 或管理后台配置(永久生效);</li>/ C. Y2 d( t6 D$ J) T1 K" b
<li>临时测试用命令行参数(重启失效);</li>
& `# m* ~5 Y- f5 \<li>自定义逻辑用钩子脚本补充。</li>3 G- p: f: g. E. m6 l  M% m
</ul>
8 q  T( }- J5 D5 k</li>. o8 i9 Q" N4 Q+ S% r" M$ g6 n
<li><strong>Debian 12 关键操作</strong>:, ]8 q  e* r# j3 x  `1 b" T
<ul>9 m) A7 @0 M3 T! H$ ^* ]) g. A
<li>修改配置文件后需重启 PocketBase(systemctl/堡塔面板);</li>
/ f* d! f. L9 P3 i1 ^( q6 e. m' ?<li>自定义路径(存储/日志)需提前创建并授权;</li>2 g8 |1 {- I4 `% J( W
<li>HTTPS 推荐用 Nginx 反向代理,而非 PocketBase 内置方式。</li>
! j& j' }/ G8 i: @6 [3 l! f8 D4 _9 [</ul>
. P4 r5 @! C9 c4 c" F" U. j</li>
& q: ~) q' h2 K% `<li><strong>生产环境必配</strong>:+ f# v& ^% C2 e6 L7 v- P- h
<ul>
4 N: C# Q% o) X& v. U<li>邮件配置(密码重置)、HTTPS(安全访问)、跨域配置(前端访问)、日志持久化(排查问题);</li>+ x6 v, D  O5 W" d
<li>配置文件定期备份,避免丢失。</li>
7 h4 Y& _( B' s% R8 T& d</ul>! x$ t/ f( J/ `
</li>
$ M2 E' h) m# i, `4 K1 y& l! ]/ a</ol>% A5 b' _. b4 @6 m+ B
<p>通过以上配置,可完全适配 Debian 12 系统下 PocketBase 的生产环境需求,兼顾安全性、稳定性和自定义性。</p>
! n5 M- s$ q, W1 n7 w6 g6 {9 x
匠心独运,千锤百炼,品质非凡。
回复

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

您需要 登录 后才可以回复,轻松玩转社区,没有帐号?立即注册
快速回复
关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表