feat: registry_api + fn sync — sincronización de registry.db entre PCs
Nuevo sistema para mantener datos no regenerables (proposals, apps, projects, analysis, vaults, pc_locations) sincronizados entre múltiples máquinas via una API HTTP central desplegada en organic-machine.com. - Migración 011: tabla pc_locations (mapa de ubicaciones por PC) - registry/models.go: struct PcLocation - registry/store.go: CRUD PcLocation + helpers de sync - cmd/fn/sync.go: subcomando fn sync (push+pull, status, locations) - bash/functions/infra/setup_registry_api: pipeline de deploy Docker+Traefik - CLAUDE.md: documentación de sync y pc_locations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: setup_registry_api
|
||||
kind: pipeline
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "setup_registry_api(ssh_host: string, api_token: string, basic_auth_user: string, basic_auth_pass: string) -> json"
|
||||
description: "Deploy completo de registry_api en VPS con Docker + Traefik (Coolify proxy). Sincroniza el repo via rsync, genera el hash bcrypt para basicAuth, sube el traefik-dynamic.yml, crea el .env con el token, hace docker compose build+up y verifica el health check."
|
||||
tags: [launcher, deploy, docker, traefik, registry, coolify, infra, ssh]
|
||||
uses_functions: [rsync_deploy_bash_infra, ssh_exec_go_infra]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
params:
|
||||
- name: ssh_host
|
||||
desc: "Alias SSH del VPS destino definido en ~/.ssh/config (default: organic-machine.com)"
|
||||
- name: api_token
|
||||
desc: "Token de autenticación para la registry_api (REGISTRY_API_TOKEN). Se escribe en el .env remoto."
|
||||
- name: basic_auth_user
|
||||
desc: "Usuario para basicAuth de Traefik (default: lucas). Se usa para generar el hash bcrypt con htpasswd."
|
||||
- name: basic_auth_pass
|
||||
desc: "Password para basicAuth de Traefik. Se hashea con bcrypt (htpasswd -nB -C 10) y se escapa a $$ para Traefik."
|
||||
output: "JSON con status (ok|error), url del servicio, http_code del health check, duration_ms, ssh_host y remote_dir. Exit code 1 si algún paso falla."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/infra/setup_registry_api.sh"
|
||||
---
|
||||
|
||||
## Requisitos previos
|
||||
|
||||
- `htpasswd` instalado localmente (`apt install apache2-utils`)
|
||||
- `rsync` instalado localmente
|
||||
- SSH alias `organic-machine.com` (o el host indicado) configurado en `~/.ssh/config`
|
||||
- El usuario SSH debe tener `sudo` sin password para `mkdir -p /data/coolify/proxy/dynamic/` y `tee` en esa ruta
|
||||
- Red Docker `coolify` existente en el VPS (se crea automáticamente si no existe)
|
||||
- Traefik corriendo con file watcher en `/data/coolify/proxy/dynamic/` (Coolify proxy estándar)
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# Forma directa como script
|
||||
bash bash/functions/infra/setup_registry_api.sh \
|
||||
organic-machine.com \
|
||||
"mi-token-secreto" \
|
||||
lucas \
|
||||
"mi-password"
|
||||
|
||||
# Como función sourced
|
||||
source bash/functions/infra/setup_registry_api.sh
|
||||
|
||||
result=$(setup_registry_api \
|
||||
"organic-machine.com" \
|
||||
"mi-token-secreto" \
|
||||
"lucas" \
|
||||
"mi-password")
|
||||
echo "$result"
|
||||
# {"status":"ok","url":"https://registry.organic-machine.com/api/status","http_code":"200","duration_ms":45231,"ssh_host":"organic-machine.com","remote_dir":"/opt/fn-registry-build/apps/registry_api"}
|
||||
|
||||
# Via variables de entorno
|
||||
export REGISTRY_API_TOKEN="mi-token-secreto"
|
||||
export BASIC_AUTH_PASS="mi-password"
|
||||
bash bash/functions/infra/setup_registry_api.sh
|
||||
```
|
||||
|
||||
## Pasos del pipeline
|
||||
|
||||
1. **Verificar SSH** — `ssh -o BatchMode=yes -o ConnectTimeout=10` para confirmar acceso al VPS
|
||||
2. **Generar hash bcrypt** — `htpasswd -nB -C 10` localmente, escapar `$` a `$$` para Traefik
|
||||
3. **rsync del repo** — sube el repo completo a `/opt/fn-registry-build/` en el VPS (el Dockerfile necesita el contexto raíz)
|
||||
4. **Subir traefik-dynamic.yml** — reemplaza el placeholder del hash en el template local y lo sube a `/data/coolify/proxy/dynamic/registry-api-organic-machine-com.yml` via `sudo tee`
|
||||
5. **Crear .env** — escribe `REGISTRY_API_TOKEN=...` en `apps/registry_api/.env` en el VPS
|
||||
6. **docker compose build && up -d** — construye la imagen (multi-stage, CGO+FTS5) y levanta el container con la red `coolify`
|
||||
7. **Health check** — polling a `https://registry.organic-machine.com/api/status` cada 10s, máximo 12 intentos (2 minutos)
|
||||
|
||||
## Notas
|
||||
|
||||
- El `docker-compose.yml` de la app usa `context: ../../` para incluir `registry/`, `functions/`, `cmd/` y `apps/registry_api/` en el build. Por eso se sincroniza el repo completo y no solo la app.
|
||||
- El Dockerfile genera el binario `registry_api` con `CGO_ENABLED=1 -tags fts5` (SQLite + FTS5). El `registry.db` se genera en el primer arranque via `fn index` dentro del container, o puede montarse externamente via el volumen `/data`.
|
||||
- Traefik detecta el cambio en `/data/coolify/proxy/dynamic/` automáticamente (file provider con file watcher), sin necesidad de reiniciar Traefik.
|
||||
- Para re-deploys: ejecutar el mismo script — rsync es idempotente y `docker compose up -d` recrea el container si la imagen cambió.
|
||||
- Si `REGISTRY_API_TOKEN` está vacío, la API arranca sin autenticación (solo basicAuth de Traefik protege el acceso).
|
||||
Reference in New Issue
Block a user