El servidor finaz-new¶
Qué vas a aprender¶
- La topología del servidor y la frontera entre el proyecto
finaz(compartido) yfinaz-trading-engine(nuestro). - Las prohibiciones operativas y por qué existen.
- Cómo se separan los roles en PostgreSQL, ClickHouse y MinIO.
- Cómo viajan los secretos (por fichero) y por qué la API solo escucha en loopback.
Ficha del servidor¶
| Qué | Valor |
|---|---|
| Host | scw-iort-indexer-metal-02, Ubuntu 24.04, 24 CPU, 251 GiB RAM, sin GPU |
| Docker | 29.1.3 / Compose 2.40.3 (inventario S0) |
| SSH de despliegue | alias finaz-new-user → usuario iort-user (grupos docker + finaz-ops, sin sudo) |
| SSH de administración | alias finaz-new → usuario iort |
| Repositorio | /home/iort-user/FinazTradingEngine (rama feat/finaz-v2) |
| Secretos | /home/iort-user/finaz-secrets-v2/ (fuera del repo) |
| API de plataforma | http://127.0.0.1:18300 (solo loopback) |
| Toolchain | ~/.local/bin (uv/uvx), node 20 |
Modo de trabajo
Desde 2026-09-19 todo se desarrolla, construye, prueba y despliega en el servidor
como iort-user. El portátil solo consulta por ssh.
Topología¶
flowchart TB
subgraph host["finaz-new (24 CPU · 251 GiB · sin GPU)"]
subgraph finaz["Proyecto finaz — EXISTENTE, no gestionado"]
PG[("finaz-postgres :5432")]
CH[("finaz-clickhouse :8123/:9000")]
RP[("finaz-redpanda :9092")]
MN[("finaz-minio :9000")]
end
NET{{"red externa finaz-net"}}
subgraph te["Proyecto finaz-trading-engine — NUESTRO"]
API["api → 127.0.0.1:18300"]
WB["worker-batch"]
WS["worker-stream"]
JB["replay + jobs S7"]
VOL[("volúmenes finaz-te-artifacts,<br/>finaz-te-jobs, finaz-te-models")]
end
PG --- NET
CH --- NET
RP --- NET
MN --- NET
NET --- API
NET --- WB
NET --- WS
NET --- JB
end
OP["Operador (ssh)"] -->|túnel / loopback| API
Los servicios del runtime encuentran PG/CH/Redpanda/MinIO por DNS interno en la red
finaz-net y trabajan solo en sus namespaces (base PG finaz_trading_engine,
base CH finaz_te, topics finaz-te-*, bucket propio en MinIO).
Prohibiciones (y su porqué)¶
Lo que nunca se hace
- Nunca
down,build,pull,pruneni migraciones sobre el proyectofinaz. - Nunca duplicar PG/CH/Redpanda/MinIO en el Compose nuevo.
- Nunca
container_name(colisiones entre proyectos). - Nunca
docker compose down -vcomo rollback (borra volúmenes). - Nunca
docker system/image/volume prune(hay otros operadores). - Nunca copiar
.envnicache/al servidor. - Nunca publicar la API fuera de loopback.
El motivo es simple: el servidor es compartido. El proyecto finaz tiene 37
contenedores de otros servicios; la QA final comprobó que seguían con IDs
idénticos tras nuestro trabajo. Los builds usan un builder dedicado te-build
porque la caché del builder por defecto se corrompió y es compartida.
Roles con mínimo privilegio (gate S1)¶
Un rol por servicio y por almacén:
| Almacén | Rol | Quién lo usa |
|---|---|---|
| PostgreSQL | finaz_te_api |
api |
| PostgreSQL | finaz_te_worker |
workers |
| PostgreSQL | finaz_te_migrator |
migraciones y backup |
| ClickHouse | finaz_te_ingest |
escritura de staging |
| ClickHouse | finaz_te_read |
lectura (y export del backup) |
| MinIO | finaz_te_app + policy |
artefactos |
Secretos por fichero¶
Regla: secretos en ficheros montados, nunca en variables de entorno
Las claves viven en ~/finaz-secrets-v2/ (permisos 600/644) y se montan
read-only en /run/secrets y /run/secrets-roles. El contenedor recibe solo
rutas *_FILE (por ejemplo FINAZ_PG_PASSWORD_FILE=/run/secrets-roles/pg_api_password).
Así, docker inspect no muestra ningún secreto (verificado en la QA final).
| Fichero | Contenido |
|---|---|
te-s2.env (600) |
Variables no secretas del despliegue (bases, hosts…) |
api_tokens.json |
Solo hashes SHA-256 de los tokens de la API |
roles/ |
Claves por rol (pg_api_password, pg_migrator_password, …) |
api_tokens_live |
Tokens vivos del operador para los smokes (nunca se imprimen) |
API solo en loopback: 18300¶
La API se publica como 127.0.0.1:18300:8000. El puerto se eligió en S0 tras
verificar con ss -lnt que estaba libre (18099, 18100 y 18430 estaban ocupados).
ss -lnt | grep 18300 # comprobar antes de publicar
curl -fsS http://127.0.0.1:18300/healthz # liveness
curl -fsS http://127.0.0.1:18300/health/ready
Desde el portátil se accede con un túnel SSH (ssh -L 18300:127.0.0.1:18300 finaz-new-user).
Arranque del entorno Compose¶
cd ~/FinazTradingEngine
export $(grep -v "^#" ~/finaz-secrets-v2/te-s2.env | xargs)
export FINAZ_API_SECRETS_DIR=$HOME/finaz-secrets-v2
export FINAZ_ROLES_DIR=$HOME/finaz-secrets-v2/roles
export FINAZ_FIXTURE_DIR=$PWD/tests_v2/fixtures_shared
export FINAZ_FLOW_DIR=$PWD/InputExternal/FINAZ_Architecture_Definition_Pack_v1/contracts/examples
export FINAZ_SPEC_DIR=$FINAZ_FLOW_DIR
docker compose -p finaz-trading-engine -f deployment/v2/compose.yaml config -q
Rebuilds
Tras cambiar código: commit, git pull en el servidor, rebuild con
docker buildx build --builder te-build --load …, y up -d solo del servicio afectado.
Resumen¶
finaz-newaloja el proyecto compartidofinazy nuestrofinaz-trading-engine, unidos porfinaz-net.- Prohibido tocar
finaz, duplicar almacenes, usardown -voprune. - Un rol por servicio en PG/CH/MinIO; secretos por fichero montado;
docker inspectlimpio. - API solo en
127.0.0.1:18300.
Para practicar¶
- ¿Qué comando usarías para verificar que el puerto 18400 está libre antes de usarlo?
- ¿Por qué pasar la clave de PG por variable de entorno es peor que por fichero?
- Enumera tres acciones que romperían servicios de otros equipos en este servidor.