跳转到内容

架构

┌──────────────────────────────────┐
│ Pier (single binary) │
│ │
Browser ───────▶ │ Axum ──▶ API routes (100+) │
│ │ │
│ ├──▶ MiniJinja ──▶ HTML (HTMX) │
│ ├──▶ Bollard ──▶ Docker Engine │
│ ├──▶ rusqlite ──▶ SQLite │
│ └──▶ reqwest ──▶ Remote Agents │
└──────────────────────────────────┘
┌───────────────┴────────────────┐
│ Traefik (reverse proxy) │
│ Let's Encrypt · Auto-routing │
└────────────────────────────────┘
层级Crate职责
HTTP + WebSocketaxumAPI 端点,以及用于日志和指标的 SSE/WebSocket 数据流
Dockerbollard所有容器、卷和网络操作
数据库rusqlite嵌入式 SQLite,采用 WAL 模式以支持并发读取
模板minijinja为仪表盘服务端渲染 HTML
认证axum-login + totp-rs不透明 cookie 会话;带恢复码的 TOTP 双因素认证
SSHrussh远程服务器配置
Gitgix用于 Git 部署的克隆和拉取
指标sysinfo系统和容器指标
缓存moka用于 Docker 统计数据的内存缓存
运行时tokio异步 I/O

UI 通过 MiniJinja 在服务端渲染。HTMX 负责局部更新;Alpine.js 处理小型交互(模态框、开关)的客户端状态。客户端 JS 总量约为 30 KB。所有资源均内嵌于二进制文件中——没有 CDN,没有外部字体,运行时也无需打包器。

/opt/pier/
├── bin/pier # the binary
├── bin/pier.old # previous version (for rollback)
├── .env # PIER_SECRET — AES-256 key for env vars
└── data/
├── pier.db # SQLite main database
├── pier.db-wal # WAL file
├── backups/ # automated DB + .env backups
└── traefik/ # dynamic config files per domain

存储在数据库中的每一个环境变量都使用 AES-256-GCM 加密。密钥来自 PIER_SECRET(32 个随机字节,经 base64 编码)——systemd 从 /opt/pier/.env 读取它;如果该变量未设置,Pier 会改为在数据目录中持久化一个 .pier-secret 文件。仅有数据库而没有密钥是毫无用处的——这种拆分是有意为之,以确保泄露的 SQL 转储不会泄露密钥。

加密是向后兼容的:在该功能上线之前写入的行可以作为纯文本读取;新写入的数据带有 ENC: 前缀,并始终加密。