Saltar al contenido principal Saltar a navegación Saltar al pie de página

Reglas de Rediacc

Información esencial sobre reglas y convenciones para crear aplicaciones en la plataforma Rediacc. Cubre Rediaccfile, compose, configuración de red, almacenamiento, CRIU e implementación.

Reglas de Rediacc

Cada repositorio de Rediacc se ejecuta dentro de un entorno aislado con su propio daemon Docker, volumen LUKS cifrado y rango de IP dedicado. Estas reglas aseguran que tu aplicación funcione correctamente dentro de esta arquitectura.

Rediaccfile

  • Cada repositorio necesita un Rediaccfile — un script bash con funciones de ciclo de vida.
  • Funciones del ciclo de vida: up(), down(). Opcional: info().
  • up() inicia tus servicios. down() los detiene.
  • info() proporciona información de estado (estado de contenedores, logs recientes, salud).
  • Rediaccfile es cargado (sourced) por renet — tiene acceso a variables de shell, no solo a variables de entorno.

Variables de entorno disponibles en Rediaccfile

VariableEjemploDescripción
REDIACC_WORKING_DIR/mnt/rediacc/mounts/abc123/Ruta raíz del repo montado
REDIACC_NETWORK_ID6336Identificador de aislamiento de red
REDIACC_REPOSITORYabc123-...GUID del repositorio
{SVCNAME}_IPHEARTBEAT_IP=127.0.24.195IP de loopback por servicio (nombre del servicio en mayúsculas)

Rediaccfile mínimo

#!/bin/bash

_compose() {
  renet compose -- "$@"
}

up() {
  _compose up -d
}

down() {
  _compose down
}

Compose

  • Usa renet compose, nunca docker compose — renet inyecta aislamiento de red, red de host, IPs de loopback y etiquetas de servicio.
  • NO establezcas network_mode en tu archivo compose — renet fuerza network_mode: host en todos los servicios. Cualquier valor que establezcas será sobrescrito.
  • NO establezcas etiquetas rediacc.* — renet auto-inyecta rediacc.network_id, rediacc.service_ip y rediacc.service_name.
  • Los mapeos de ports: se ignoran en modo de red de host. Usa la etiqueta rediacc.service_port para enrutar el proxy a puertos que no sean el 80.
  • Las políticas de reinicio (restart: always, on-failure, etc.) son seguras de usar — renet las elimina automáticamente para compatibilidad con CRIU. El watchdog del router recupera automáticamente los contenedores detenidos según la política original guardada en .rediacc.json.
  • Los ajustes peligrosos están bloqueados por defectoprivileged: true, pid: host, ipc: host y bind mounts a rutas del sistema son rechazados. Usa renet compose --unsafe para anularlo bajo tu propio riesgo.

Variables de entorno dentro de los contenedores

Renet auto-inyecta estas en cada contenedor:

VariableDescripción
SERVICE_IPIP de loopback dedicada de este contenedor
REDIACC_NETWORK_IDID de aislamiento de red

Nombres de servicios y enrutamiento

  • The compose service name becomes the auto-route URL prefix.
  • Grand repos: https://{service}.{repo}.{machine}.{baseDomain} (ej.: https://myapp.marketing.server-1.example.com).
  • Fork repos: https://{service}-{tag}.{machine}.{baseDomain} — uses the machine wildcard cert to avoid Let’s Encrypt rate limits.
  • Para dominios personalizados, use etiquetas de Traefik (nota: los dominios personalizados NO son compatibles con fork — el dominio pertenece al grand repo).

Redes

  • Cada repositorio tiene su propio daemon Docker en /var/run/rediacc/docker-<networkId>.sock.
  • Cada servicio recibe una IP de loopback única dentro de una subred /26 (ej. 127.0.24.192/26).
  • Enlázate a SERVICE_IP — cada servicio obtiene una IP de loopback única.
  • Los health checks deben usar ${SERVICE_IP}, no localhost. Ejemplo: healthcheck: test: ["CMD", "curl", "-f", "http://${SERVICE_IP}:8080/health"]
  • Comunicación entre servicios: Usa IPs de loopback o la variable de entorno SERVICE_IP. Los nombres DNS de Docker NO funcionan en modo host.
  • Los conflictos de puertos son imposibles entre repositorios — cada uno tiene su propio daemon Docker y rango de IP.
  • Reenvío de puertos TCP/UDP: Agrega etiquetas para exponer puertos no HTTP:
    labels:
      - "rediacc.tcp_ports=5432,3306"
      - "rediacc.udp_ports=53"

Almacenamiento

  • Todos los datos Docker se almacenan dentro del repo cifrado — el data-root de Docker está en {mount}/.rediacc/docker/data dentro del volumen LUKS. Los volúmenes nombrados, imágenes y capas de contenedores están todos cifrados, respaldados y se forkean automáticamente.
  • Los bind mounts a ${REDIACC_WORKING_DIR}/... se recomiendan por claridad, pero los volúmenes nombrados también funcionan de forma segura.
    volumes:
      - ${REDIACC_WORKING_DIR}/data:/data        # bind mount (recomendado)
      - pgdata:/var/lib/postgresql/data      # named volume (también seguro)
  • El volumen LUKS se monta en /mnt/rediacc/mounts/<guid>/.
  • Las instantáneas BTRFS capturan todo el archivo de respaldo LUKS, incluyendo todos los datos montados con bind.
  • El datastore es un archivo de pool BTRFS de tamaño fijo en el disco del sistema. Usa rdc machine query <name> --system para ver el espacio libre efectivo. Amplía con rdc datastore resize.

CRIU (Migración en vivo)

  • Activación por etiqueta: Añada rediacc.checkpoint=true a los contenedores que desee checkpointear. Los contenedores sin esta etiqueta (bases de datos, cachés) se inician desde cero y se recuperan mediante sus propios mecanismos (WAL, LDF, AOF).
  • backup push --checkpoint captura el estado de memoria de procesos en ejecución + estado del disco para contenedores etiquetados.
  • repo fork --checkpoint captura el estado del proceso antes del fork — el fork se restaura automáticamente con repo up.
  • repo down --checkpoint guarda el estado del proceso antes de detenerse — el siguiente repo up restaura automáticamente.
  • repo up detecta automáticamente datos de checkpoint y restaura si los encuentra. Use --skip-checkpoint para inicio limpio.
  • Restauración con reconocimiento de dependencias: Usa depends_on de compose para iniciar bases de datos primero (esperar healthy), luego restaurar CRIU de contenedores de aplicación.
  • Las conexiones TCP se vuelven obsoletas después de la restauración — las aplicaciones deben manejar ECONNRESET y reconectarse.
  • El modo experimental de Docker se activa automáticamente en los daemons por repositorio.
  • CRIU se instala durante rdc config machine setup.
  • /etc/criu/runc.conf se configura con tcp-established para preservación de conexiones TCP.
  • La configuración de seguridad se inyecta automáticamente para contenedores etiquetadosrenet compose añade lo siguiente a contenedores con rediacc.checkpoint=true:
    • cap_add: CHECKPOINT_RESTORE, SYS_PTRACE, NET_ADMIN (conjunto mínimo para CRIU en kernel 5.9+)
    • security_opt: apparmor=unconfined (el soporte de AppArmor en CRIU aún no es estable)
    • userns_mode: host (CRIU requiere acceso al namespace init para /proc/pid/map_files)
  • Los contenedores sin la etiqueta ejecutan con una postura de seguridad más limpia (sin capabilities extra).
  • El perfil seccomp predeterminado de Docker se mantiene — CRIU usa PTRACE_O_SUSPEND_SECCOMP (kernel 4.3+) para suspender temporalmente los filtros durante checkpoint/restore.
  • NO configure las capabilities de CRIU manualmente en su archivo compose — renet se encarga según la etiqueta.
  • Consulta la plantilla heartbeat para una implementación de referencia compatible con CRIU.

Patrones de aplicación compatibles con CRIU

  • Maneja ECONNRESET en todas las conexiones persistentes (pools de base de datos, websockets, colas de mensajes).
  • Usa bibliotecas de pool de conexiones que soporten reconexión automática.
  • Agrega process.on("uncaughtException") como red de seguridad para errores de sockets obsoletos de objetos internos de bibliotecas.
  • Las políticas de reinicio son gestionadas automáticamente por renet (eliminadas para CRIU, el watchdog gestiona la recuperación).
  • Evita depender del DNS de Docker — usa IPs de loopback para la comunicación entre servicios.

Seguridad

  • El cifrado LUKS es obligatorio para repositorios estándar. Cada repo tiene su propia clave de cifrado.
  • Las credenciales se almacenan en la configuración del CLI (~/.config/rediacc/rediacc.json). Perder la configuración significa perder acceso a los volúmenes cifrados.
  • Nunca hagas commit de credenciales en el control de versiones. Usa env_file y genera secretos en up().
  • Aislamiento de repositorio: El daemon Docker, la red y el almacenamiento de cada repo están completamente aislados de otros repos en la misma máquina.
  • Aislamiento de agentes: Los agentes de IA operan en modo solo-fork por defecto. Cada repo tiene su propia clave SSH con aplicación de sandbox del lado del servidor (ForceCommand sandbox-gateway). Todas las conexiones están en sandbox con Landlock LSM, overlay OverlayFS del home y TMPDIR por repo. El acceso al sistema de archivos entre repos está bloqueado por el kernel.

Despliegue

  • rdc repo up ejecuta up() en todos los Rediaccfiles.
  • rdc repo up --mount abre primero el volumen LUKS y luego ejecuta el ciclo de vida. Requerido después de backup push a una nueva máquina.
  • rdc repo down ejecuta down() y detiene el daemon Docker.
  • rdc repo down --unmount también cierra el volumen LUKS (bloquea el almacenamiento cifrado).
  • Forks (rdc repo fork) crean un clon CoW (copy-on-write) con nuevo GUID y networkId. El fork comparte la clave de cifrado del padre.
  • Takeover (rdc repo takeover <fork> -m <machine>) reemplaza los datos del repo grand con los datos de un fork. El grand mantiene su identidad (GUID, networkId, dominios, autostart, cadena de backups). Los datos de producción antiguos se conservan como un fork de backup. Úsalo para: probar una actualización en un fork, verificar, luego hacer takeover a producción. Revertir con rdc repo takeover <backup-fork> -m <machine>.
  • Las rutas del proxy tardan ~3 segundos en activarse después del despliegue. La advertencia “Proxy is not running” durante repo up es informativa en entornos de ops/dev.

Errores comunes

  • Usar docker compose en lugar de renet compose — los contenedores no obtendrán aislamiento de red.
  • Las políticas de reinicio son seguras — renet las elimina automáticamente y el watchdog gestiona la recuperación.
  • Usar privileged: true — no es necesario, renet inyecta capacidades CRIU específicas en su lugar.
  • No enlazarse a SERVICE_IP — causa conflictos de puertos entre repos.
  • Codificar IPs de forma fija — usa la variable de entorno SERVICE_IP; las IPs se asignan dinámicamente por networkId.
  • Olvidar --mount en el primer despliegue después de backup push — el volumen LUKS necesita apertura explícita.
  • Usar rdc term -c como solución alternativa para comandos fallidos — reporta bugs en su lugar.
  • repo delete realiza una limpieza completa incluyendo IPs de loopback y unidades systemd. Ejecuta rdc machine prune <name> para limpiar los restos de eliminaciones antiguas.