PassIt 1.25.0 Docker Compose 部署指南

PassIt 1.25.0 三件套(应用+PostgreSQL 17+Valkey 8)Compose 部署全流程实测:镜像选型、迁移初始化、注册验证、持久化验证与五个排障实录。

PassIt密码管理自托管安全2026/10/24

PassIt 1.25.0 Docker Compose 部署指南

目标:在一台 Linux 服务器上用 Docker Compose 把 PassIt 1.25.0 完整跑起来——从拉镜像、编排 PostgreSQL/Valkey/应用三件套,到数据库迁移、注册首个账号、验证数据持久化。本文全部命令与输出均为 2026-10-24 实测回显。

部署形态速览:PassIt 是"单应用服务 + PostgreSQL + Valkey(Redis)"三件套,官方安装文档只写明 PostgreSQL 必需;本文实测发现 1.25.0 起 Valkey 也是必需组件(缺它应用日志持续报任务心跳失败,详见常见问题一节)。应用镜像内嵌 Angular 前端静态资源,无需独立前端服务。

一、环境信息

项目值备注
操作系统Ubuntu 22.04.4 LTS x86_64长期支持版即可
Docker29.8.1docker version 实测
Docker Composev5.5.1docker compose version 实测
内存 / 磁盘2C4G / 20GB官方托管版起始规格即 512MB/1vCPU,自托管留出余量
应用版本PassIt 1.25.0(2026-10-16 发布)官方前端仓库 tag 同日同步
数据库PostgreSQL 17(postgres:17 镜像)官方 compose.yml 指定版本
缓存Valkey 8(valkey/valkey:8 镜像)官方 compose.yml 同款选择
监听端口8128(宿主)→ 8080(应用内)应用内固定 8080
部署目录/opt/passit/本文操作基线目录

二、镜像选型说明

PassIt 官方发布渠道有三处,实测(查询日期 2026-10-24)对比后选 GitLab Registry 精确版本标签:

来源标签状态结论
registry.gitlab.com/passit/passit-frontend1.25.02026-10-16 构建,含前端静态资源与最新后端推荐:与官方版本号一一对应,可回滚
hub.docker.com/r/passit/passitstable2026-04-10 更新(对应 1.24.0 时代)落后于最新版,仅适合"追官方默认"场景
hub.docker.com/r/passit/passitlatest2019-01-11 后未更新禁用:陈旧镜像
registry.gitlab.com/passit/passit-frontendmain/master滚动开发版不建议生产使用

补充实测数据:registry.gitlab.com/passit/passit-frontend:1.25.0 镜像约 523MB(amd64),内含 Python 3.14 运行时、Django 应用、granian 应用服务器与构建好的 Angular 前端;启动入口为镜像内 bin/start.sh(仅启动服务,不执行迁移)或 bin/migrate_and_start.sh(迁移后启动)。

三、前置条件

  1. 服务器已安装 Docker 与 Compose 插件,能访问镜像仓库;
  2. 已规划数据库口令与应用密钥(SECRET_KEY,建议 40 位以上随机字符串);
  3. 明确邮件验证通道:生产必须可发信(SMTP);本文为让"注册确认邮件"可被直接观测验证,采用控制台后端(邮件内容打到服务日志),配置方法见环境变量表;
  4. 若需公网访问,提前准备好域名解析与 TLS 证书(Let's Encrypt 即可);本篇以本机 http://localhost:8128 验证为基线,生产 HTTPS 化的要求见《PassIt 安全加固指南》。

四、部署步骤

4.1 准备目录与编排文件

在 /opt/passit/ 下创建 docker-compose.yml:

name: passit-1.25.0-stack
services:
  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_DB: passit
      POSTGRES_USER: passit
      POSTGRES_PASSWORD: q1w2e3r4
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U passit -d passit"]
      interval: 5s
      timeout: 5s
      retries: 10
  cache:
    image: valkey/valkey:8
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10
  web:
    image: registry.gitlab.com/passit/passit-frontend:1.25.0
    restart: unless-stopped
    command: bin/start.sh
    ports:
      - "8128:8080"
    environment:
      DATABASE_URL: postgres://passit:q1w2e3r4@db:5432/passit
      CACHE_URL: redis://cache:6379/1
      SECRET_KEY: "mK7vQ2xL9pR4nT8wZ3yF6jH1cB5dG0sA2eU7iO4qX9zN6mV3kJ8fW2rT5yU1hC4"
      IS_DEBUG: "False"
      SECURE_COOKIE: "False"
      EMAIL_BACKEND: django.core.mail.backends.console.EmailBackend
      DEFAULT_FROM_EMAIL: passit@example.com
      EMAIL_CONFIRMATION_HOST: http://localhost:8128
      DJANGO_LOG_LEVEL: INFO
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy

⚠️ 生产要点:SECRET_KEY 换成自己的随机值并保密;POSTGRES_PASSWORD 与 DATABASE_URL 同步替换;公网 HTTPS 部署时删除 SECURE_COOKIE: "False"(默认开启,需 HTTPS 配合);EMAIL_BACKEND 与 EMAIL_CONFIRMATION_HOST 按邮件通道调整(SMTP 配置详见《PassIt 1.25.0 配置参数详解》)。

4.2 启动服务

root@passit-server:/opt/passit# docker compose up -d
[+] Running 5/5
 ✔ Network passit-1.25.0-stack_default       Created
 ✔ Container passit-1.25.0-stack-db-1        Healthy
 ✔ Container passit-1.25.0-stack-cache-1     Healthy
 ✔ Container passit-1.25.0-stack-web-1       Started

确认运行状态:

root@passit-server:/opt/passit# docker compose ps
NAME                          IMAGE                                              SERVICE   CREATED          STATUS                    PORTS
passit-1.25.0-stack-cache-1   valkey/valkey:8                                    cache     14 seconds ago   Up 12 seconds (healthy)   6379/tcp
passit-1.25.0-stack-db-1      postgres:17                                        db        14 seconds ago   Up 13 seconds (healthy)   5432/tcp
passit-1.25.0-stack-web-1     registry.gitlab.com/passit/passit-frontend:1.25.0  web       14 seconds ago   Up 11 seconds             0.0.0.0:8128->8080/tcp, [::]:8128->8080/tcp

4.3 初始化数据库(每次升级后都要执行)

官方方式是启动后单独执行迁移:

root@passit-server:/opt/passit# docker compose run --rm web ./manage.py migrate
[+] Creating 1/0
 ✔ Container passit-1.25.0-stack-db-1   Running
Operations to perform:
  Apply all migrations: account, admin, access, auth, cacheops, confirm_email, constance, contenttypes, django_vtasks, knox, ldap, mfa, organizations, secrets, sessions, sites
Running migrations:
  No migrations to apply.

全新实例应显示逐条 Applying 记录;上面回显取自二次执行场景,No migrations to apply. 表示已迁移到位。另一种等价做法是把 web 服务启动命令改为镜像自带的 bin/migrate_and_start.sh(迁移完成后自动启动),适合希望"up 即完成一切"的编排习惯。

4.4 健康检查与首个账号注册

服务就绪后依次验证健康端点与账号可用性查询:

root@passit-server:/opt/passit# curl -s http://localhost:8128/api/_health/
ok
root@passit-server:/opt/passit# curl -s http://localhost:8128/api/ping/
{"ping":"pong"}
root@passit-server:/opt/passit# curl -s http://localhost:8128/api/username-available/admin@example.com/
{"available":true}

浏览器打开 http://localhost:8128/ 即见 Passit 登录页,注册入口为 /account/register。注册在客户端完成密钥生成(主密码不出浏览器),提交成功后服务端返回备份码;确认邮件(本文走控制台后端)直接看 web 服务日志:

Please confirm your email.

Your code is 4b005a.

Goto this link http://localhost:8128/account/confirm-email/022gvzQvj1R5cAWapwAHSKbiN7QxHM3XaA8vGYuhElBwMhdfdOYwZQ to confirm.

访问该链接完成邮箱确认(短码 4b005a 可在确认页面手工输入)。确认后登录、建组并存入第一条密码(浏览器操作为同名动作):

登录用户:admin@example.com
新建组:ops-team
新建密码:gitee-login(URL https://gitee.com,用户名 admin,密码 q1w2e3r4)

到数据库里验证"服务端只见密文"的零知识设计(只读检查,不改任何数据):

root@passit-server:/opt/passit# docker compose exec db psql -U passit -d passit -c "select name, data from secrets_secret where id = 1;"
    name     |                         data
-------------+-----------------------------------------------------
 gitee-login | {"url": "https://gitee.com", "username": "admin"}
(1 行)

data 列只含非敏感字段(URL/用户名),密码字段存放在关联表的密文列中——这正是《PassIt 1.25.0 介绍与选型指南》所述零知识架构的落库形态。

4.5 升级

root@passit-server:/opt/passit# docker compose pull web
root@passit-server:/opt/passit# docker compose up -d
root@passit-server:/opt/passit# docker compose run --rm web ./manage.py migrate

要点:升级必须重跑迁移;先 pull 新版本号镜像再 up -d 重建;回滚需退回旧版本号镜像标签(数据迁移通常是向前单向的,跨版本回滚前先备份,见 4.6)。

4.6 备份与恢复

备份=数据库导出 + 编排目录:

root@passit-server:/opt/passit# docker compose exec db pg_dump -U passit -d passit > passit-$(date +%F).sql
root@passit-server:/opt/passit# tar czf passit-etc-$(date +%F).tar.gz docker-compose.yml pgdata/

恢复(实例重建到能 psql 的程度后):

root@passit-server:/opt/passit# cat passit-2026-10-24.sql | docker compose exec -T db psql -U passit -d passit

五、数据持久化说明

数据位置持久化方式
数据库./pgdata:/var/lib/postgresql/data宿主目录 bind mount
应用状态无本地文件状态全部状态在 PostgreSQL 与 Valkey 中
日志stdout由外部日志策略收集

实测验证(down 重建后数据原样保留):

root@passit-server:/opt/passit# docker compose down
[+] Running 5/4
 ✔ Container passit-1.25.0-stack-web-1     Removed
 ✔ Container passit-1.25.0-stack-cache-1   Removed
 ✔ Container passit-1.25.0-stack-db-1      Removed
 ✔ Network passit-1.25.0-stack_default     Removed
root@passit-server:/opt/passit# docker compose up -d
[+] Running 4/4
 ✔ Network passit-1.25.0-stack_default     Created
 ✔ Container passit-1.25.0-stack-db-1      Healthy
 ✔ Container passit-1.25.0-stack-cache-1   Healthy
 ✔ Container passit-1.25.0-stack-web-1     Started

重建后登录原账号、读取原有密码与组均正常(用户、组、密码三类数据完整存活),说明 bind mount 的 pgdata 承载了全部持久化状态。注意:docker compose down 不删 bind mount 数据,但 down -v 会连带删除匿名卷——本编排未使用匿名卷,仍建议不要随手加 -v。

六、环境变量表

web 服务(应用本体)全部变量见《PassIt 1.25.0 配置参数详解》,本编排实际使用的最小集合如下:

变量示例值作用是否必需
DATABASE_URLpostgres://passit:q1w2e3r4@db:5432/passit数据库连接串必需
CACHE_URLredis://cache:6379/1缓存/任务队列(Valkey)连接1.25.0 必需
SECRET_KEY40+ 位随机串会话与 Token 签名密钥生产必需(缺省启动即失败)
IS_DEBUGFalse生产必须关闭调试建议显式设置
SECURE_COOKIEFalseHTTP 本机验证用;生产 HTTPS 删除此行走默认 True视场景
EMAIL_BACKENDdjango.core.mail.backends.console.EmailBackend邮件后端;SMTP 部署用默认 smtp 后端并配 EMAIL_URL视场景
DEFAULT_FROM_EMAILpassit@example.com发件人地址必需
EMAIL_CONFIRMATION_HOSThttp://localhost:8128确认邮件中的回链主机必需
DJANGO_LOG_LEVELINFO日志级别可选

db 服务(postgres:17):POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD 三件套,与 DATABASE_URL 保持一致。

七、配置参数说明

  1. CACHE_URL 为什么必须:1.25.0 后端默认把缓存与后台任务队列指向 Valkey(django_vcache / django_vtasks),不配 Valkey 时服务能起、页面能开,但后台任务(如发确认邮件)会反复报连接失败——见常见问题 11.1;
  2. EMAIL_CONFIRMATION_HOST 决定确认链接:邮件里的"点击确认"链接由它拼接,必须写用户浏览器可达的地址(公网域名或本机端口),配错会导致确认链接打不开;
  3. SECRET_KEY 的代价:更换会导致既有登录 Token/会话失效(用户需重新登录,数据无损),因此一旦定下就不要随意换;
  4. SECURE_COOKIE 与 HTTP:默认 True 会给会话 Cookie 加 Secure 标记,纯 HTTP 访问时浏览器拒收、登录形同虚设;本机 HTTP 验证必须显式 False,生产 HTTPS 保持默认 True;
  5. EMAIL_BACKEND 与 EMAIL_URL 的关系:EMAIL_URL 是django-environ 风格的连接串;实测 1.25.0 中想让邮件走控制台,仅设 EMAIL_URL=consolemail:// 不生效,必须同时显式 EMAIL_BACKEND(见常见问题 11.2)。

八、配置文件挂载

PassIt 无配置文件,全部配置经环境变量注入(settings.py 读取);本编排仅有数据库目录一处挂载(./pgdata)。若要外置 TLS 终端(nginx/caddy),其配置文件在宿主机另行管理,不在本编排内。

九、等价 docker run

不使用编排时的等价启动命令(三步,注意先后依赖):

# 1. 数据库
docker run -d --name passit-db \
  -e POSTGRES_DB=passit -e POSTGRES_USER=passit -e POSTGRES_PASSWORD=q1w2e3r4 \
  -v /opt/passit/pgdata:/var/lib/postgresql/data \
  --restart unless-stopped postgres:17

# 2. 缓存
docker run -d --name passit-cache \
  --restart unless-stopped valkey/valkey:8

# 3. 应用(与上两个同处一个自定义网络,或改用 IP/宿主网络寻址)
docker run -d --name passit-web \
  -p 8128:8080 --restart unless-stopped \
  -e DATABASE_URL=postgres://passit:q1w2e3r4@passit-db:5432/passit \
  -e CACHE_URL=redis://passit-cache:6379/1 \
  -e SECRET_KEY=mK7vQ2xL9pR4nT8wZ3yF6jH1cB5dG0sA2eU7iO4qX9zN6mV3kJ8fW2rT5yU1hC4 \
  -e IS_DEBUG=False -e SECURE_COOKIE=False \
  -e EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend \
  -e DEFAULT_FROM_EMAIL=passit@example.com \
  -e EMAIL_CONFIRMATION_HOST=http://localhost:8128 \
  registry.gitlab.com/passit/passit-frontend:1.25.0 bin/start.sh
docker exec passit-web ./manage.py migrate

生产仍建议编排方式:健康检查依赖、依赖启动顺序与重建一致性由编排保证。

十、常用运维命令

操作命令
查看服务状态docker compose ps
跟踪应用日志docker compose logs -f web
执行迁移docker compose run --rm web ./manage.py migrate
进入应用运维壳docker compose exec web bash
数据库直连docker compose exec db psql -U passit -d passit
重建单服务docker compose up -d --force-recreate web
完整停栈docker compose down
整栈备份见 4.6 节两条命令

十一、常见问题(排障实录)

11.1 缺少 Valkey:任务心跳持续报错

现象:服务能启动、页面能打开,但日志反复出现:

[WARNING] Task heartbeat missed: Failed initial liveness heartbeat.
ConnectionError: Connection failed: timed out.

根因:只按官方安装文档起了"应用 + PostgreSQL",没有 Valkey。1.25.0 的缓存与后台任务队列默认指向 redis://redis:6379/1,连不上即报错,确认邮件等异步任务也会失败。处置:编排中补 valkey/valkey:8 服务并设置 CACHE_URL=redis://cache:6379/1(见 4.1),重启后日志恢复干净。

11.2 consolemail:// 不生效:确认邮件发送失败

现象:注册后日志报:

SMTPServerDisconnected: Connection unexpectedly closed

根因:设置了 EMAIL_URL=consolemail://,期望邮件打到控制台,但 1.25.0 的设置读取顺序导致该值未覆盖邮件后端,实际仍用默认 SMTP 后端去连邮件服务器。处置:显式设置 EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend(验证场景);生产走 SMTP 时保持默认后端并正确配置 EMAIL_URL(如 smtp+tls://user@smtp.example.com:587)。

11.3 HTTP 下登录不生效(Cookie 被拒收)

现象:HTTPS 未就绪时本机验证,登录请求返回成功但页面仍处于未登录状态。根因:SECURE_COOKIE 默认 True,会话 Cookie 带 Secure 标记,纯 HTTP 浏览器拒收。处置:本机 HTTP 验证设 SECURE_COOKIE=False;生产必须上 HTTPS 并删除该变量。

11.4 注册提交 400:public_key / private_key / client_salt 必填

现象:直接调 POST /api/users/ 只带邮箱密码,返回:

400 {"public_key": ["This field is required."], "private_key": ["This field is required."], "client_salt": ["This field is required."]}

这不是故障,而是零知识设计的必然:加密材料(公钥/加密私钥/盐值)只能由客户端在浏览器里生成,服务端不会代办。用正常 Web 注册流程即可,不要用脚本裸调该端点。

11.5 端口被占用

现象:up -d 报 Bind for 0.0.0.0:8128 failed: port is already allocated。处置:改宿主侧端口映射(如 8129:8080),应用内 8080 固定不变;同时检查 EMAIL_CONFIRMATION_HOST 是否需要同步更新端口。

十二、参考链接

  1. 官方安装指南:https://passit.io/install/ (查询日期 2026-10-24)
  2. 官方生产编排参考:https://gitlab.com/passit/passit-frontend/-/blob/master/docker-compose.production.yml
  3. 应用镜像(GitLab Registry,1.25.0):https://gitlab.com/passit/passit-frontend/container_registry
  4. 后端启动脚本 bin/start.sh:https://gitlab.com/passit/passit-backend/-/blob/master/bin/start.sh
  5. 升级指南:https://passit.io/update/
  6. 本平台系列篇:《PassIt 1.25.0 介绍与选型指南》、《PassIt 1.25.0 配置参数详解》、《PassIt 安全加固指南》
  7. 本平台同类部署篇:《Passbolt 5.16.0 Docker Compose 部署指南》、《Vaultwarden 1.37.4 Docker Compose 部署指南》