Ir al contenido

Arquitectura

┌──────────────────────────────────┐
│ 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 │
└────────────────────────────────┘
CapaCrateFunción
HTTP + WebSocketaxumEndpoints de API y flujos SSE/WebSocket para registros y métricas
DockerbollardTodas las operaciones de contenedores, volúmenes y redes
Base de datosrusqliteSQLite embebido, modo WAL para lecturas concurrentes
PlantillasminijinjaHTML renderizado en el servidor para el panel de control
Autenticaciónaxum-login + totp-rsSesiones opacas por cookie; 2FA con TOTP y códigos de recuperación
SSHrusshAprovisionamiento de servidores remotos
GitgixClone y pull para el despliegue desde Git
MétricassysinfoMétricas del sistema y de los contenedores
CachémokaCaché en memoria para las estadísticas de Docker
RuntimetokioE/S asíncrona

La interfaz se renderiza en el servidor con MiniJinja. HTMX gestiona las actualizaciones parciales; Alpine.js cubre el estado del lado del cliente para interacciones pequeñas (modales, conmutadores). El total de JS del lado del cliente ronda los 30 KB. Todo se entrega embebido en el binario: sin CDN, sin fuentes externas, sin bundler en tiempo de ejecución.

/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

Cada variable de entorno almacenada en la base de datos se cifra con AES-256-GCM. La clave proviene de PIER_SECRET (32 bytes aleatorios, codificados en base64): systemd la lee desde /opt/pier/.env, y si la variable no está definida, Pier persiste en su lugar un archivo .pier-secret en el directorio de datos. La base de datos por sí sola es inútil sin la clave: la separación es intencional, de modo que un volcado SQL filtrado no filtre los secretos.

El cifrado es retrocompatible: las filas escritas antes de que se lanzara la funcionalidad se pueden leer como texto plano; las nuevas escrituras llevan un prefijo ENC: y siempre están cifradas.