Saltar a contenido

El servidor finaz-new

Qué vas a aprender

  • La topología del servidor y la frontera entre el proyecto finaz (compartido) y finaz-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, prune ni migraciones sobre el proyecto finaz.
  • Nunca duplicar PG/CH/Redpanda/MinIO en el Compose nuevo.
  • Nunca container_name (colisiones entre proyectos).
  • Nunca docker compose down -v como rollback (borra volúmenes).
  • Nunca docker system/image/volume prune (hay otros operadores).
  • Nunca copiar .env ni cache/ 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-new aloja el proyecto compartido finaz y nuestro finaz-trading-engine, unidos por finaz-net.
  • Prohibido tocar finaz, duplicar almacenes, usar down -v o prune.
  • Un rol por servicio en PG/CH/MinIO; secretos por fichero montado; docker inspect limpio.
  • API solo en 127.0.0.1:18300.

Para practicar

  1. ¿Qué comando usarías para verificar que el puerto 18400 está libre antes de usarlo?
  2. ¿Por qué pasar la clave de PG por variable de entorno es peor que por fichero?
  3. Enumera tres acciones que romperían servicios de otros equipos en este servidor.