From 0397fc8cc4ad85cce4fad0aa41cb5f60d03e155b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9nich=20Bon=20=C4=86iri=C4=87?= Date: Thu, 8 Oct 2026 22:17:27 -0600 Subject: [PATCH] feat(mirrors): initial architecture, specifications, automation tools, and canonical guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Establish community mirror network on IPFS for Fedora and CentOS Stream 10: - Modular documentation and specifications under docs/ - Master canonical guide under README.rst with client and node operator workflows - Ingestion, upstream sync, and Cloudflare DNSLink automation scripts in bin/ - Reverse proxy configs (Nginx/Caddy) and systemd timer units in etc/ and systemd/ Signed-off-by: Rénich Bon Ćirić Co-authored-by: Gemini AI --- .gitignore | 7 + README.rst | 237 ++++++++++++++++++ bin/mxos-dnslink-update.bash | 118 +++++++++ bin/mxos-mirror-ingest.bash | 92 +++++++ bin/mxos-mirror-sync.bash | 159 ++++++++++++ bin/mxos-mirror.bash | 141 +++++++++++ docs/business/spec.rst | 18 ++ docs/business/specs/incentivos-comunidad.rst | 27 ++ docs/business/specs/mision-vision.rst | 28 +++ docs/functional/spec.rst | 26 ++ docs/functional/specs/catalogo-modular.rst | 40 +++ docs/functional/specs/pineo-granular.rst | 34 +++ docs/functional/specs/tablero-metricas.rst | 21 ++ docs/guides/cliente-dnf.rst | 68 +++++ docs/guides/hazlo-tu-mismo.rst | 73 ++++++ docs/guides/index.rst | 17 ++ docs/guides/operador-nodo.rst | 84 +++++++ docs/index.rst | 19 ++ docs/project/roadmap.rst | 38 +++ docs/project/roadmaps/fase-1-poc.rst | 45 ++++ docs/project/roadmaps/fase-2-tablero.rst | 42 ++++ .../roadmaps/fase-3-federacion-upstream.rst | 37 +++ docs/technical/spec.rst | 27 ++ .../specs/arquitectura-distribucion.rst | 58 +++++ docs/technical/specs/ingesta-repositorios.rst | 31 +++ docs/technical/specs/puente-mirrormanager.rst | 68 +++++ docs/technical/specs/resolucion-dnslink.rst | 32 +++ etc/caddy/Caddyfile | 25 ++ etc/mirrors.env | 19 ++ etc/nginx/mirrors.mx-os.mx.conf | 43 ++++ systemd/mxos-mirror.service | 15 ++ systemd/mxos-mirror.timer | 11 + 32 files changed, 1700 insertions(+) create mode 100644 .gitignore create mode 100644 README.rst create mode 100755 bin/mxos-dnslink-update.bash create mode 100755 bin/mxos-mirror-ingest.bash create mode 100755 bin/mxos-mirror-sync.bash create mode 100755 bin/mxos-mirror.bash create mode 100644 docs/business/spec.rst create mode 100644 docs/business/specs/incentivos-comunidad.rst create mode 100644 docs/business/specs/mision-vision.rst create mode 100644 docs/functional/spec.rst create mode 100644 docs/functional/specs/catalogo-modular.rst create mode 100644 docs/functional/specs/pineo-granular.rst create mode 100644 docs/functional/specs/tablero-metricas.rst create mode 100644 docs/guides/cliente-dnf.rst create mode 100644 docs/guides/hazlo-tu-mismo.rst create mode 100644 docs/guides/index.rst create mode 100644 docs/guides/operador-nodo.rst create mode 100644 docs/index.rst create mode 100644 docs/project/roadmap.rst create mode 100644 docs/project/roadmaps/fase-1-poc.rst create mode 100644 docs/project/roadmaps/fase-2-tablero.rst create mode 100644 docs/project/roadmaps/fase-3-federacion-upstream.rst create mode 100644 docs/technical/spec.rst create mode 100644 docs/technical/specs/arquitectura-distribucion.rst create mode 100644 docs/technical/specs/ingesta-repositorios.rst create mode 100644 docs/technical/specs/puente-mirrormanager.rst create mode 100644 docs/technical/specs/resolucion-dnslink.rst create mode 100644 etc/caddy/Caddyfile create mode 100644 etc/mirrors.env create mode 100644 etc/nginx/mirrors.mx-os.mx.conf create mode 100644 systemd/mxos-mirror.service create mode 100644 systemd/mxos-mirror.timer diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63671d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Archivos locales y temporales +*.log +*.tmp +staging/ +logs/ +cache/ +.DS_Store diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..df28870 --- /dev/null +++ b/README.rst @@ -0,0 +1,237 @@ +========================================================= +Red de Espejos Comunitarios de Software Libre sobre IPFS +========================================================= + +Infraestructura de distribución soberana, descentralizada y de alta resiliencia para distribuciones Linux de la familia RPM, operada por la `Fundación MxOS`_ bajo el dominio canónico ``mirrors.mx-os.mx``. + +.. _Fundación MxOS: https://mx-os.mx + +Propósito y Misión +================== +Históricamente, los usuarios e instituciones en México y Latinoamérica han dependido de espejos universitarios aislados o enlaces transfronterizos hacia redes de entrega de contenido comerciales en Estados Unidos. Esta dependencia genera latencia, costos recurrentes de transferencia y vulnerabilidad ante caídas de enlaces internacionales. + +La red de espejos de MxOS replantea la entrega de paquetes utilizando el Sistema de Archivos Interplanetario (IPFS). Al emplear direccionamiento por contenido y distribución entre pares (P2P), el espejo se convierte en una red colaborativa donde cualquier integrante de la comunidad o institución académica puede donar almacenamiento y ancho de banda local, deduplicando transferencias y acelerando descargas dentro de redes locales o nacionales. + +Arquitectura y Principios de Operación +====================================== +El sistema opera sobre cuatro pilares técnicos: + +1. **Direccionamiento por contenido inmutable:** Cada archivo, paquete RPM y metadato se divide en bloques criptográficos referenciados por su identificador de contenido (CID). Si dos versiones comparten paquetes idénticos, estos se deduplican en el almacenamiento global. +2. **Distribución entre pares con Bitswap:** Al solicitar un paquete, el demonio Kubo lo descarga simultáneamente de todos los nodos guardianes disponibles que lo posean en la red local o internet (puerto 4001 TCP/UDP). +3. **Puntero canónico con DNSLink:** Para evitar lidiar con hashes cambiantes en cada sincronización, el dominio ``mirrors.mx-os.mx`` cuenta con registros TXT DNSLink (``_dnslink.mirrors.mx-os.mx``) que apuntan al CID raíz más reciente con una propagación de 300 segundos. +4. **Puente HTTP para compatibilidad universal:** Quienes no cuenten con un nodo IPFS pueden consumir el espejo directamente a través de HTTP/HTTPS mediante el terminador web que reenvía peticiones hacia el enjambre. + +Consumo del Espejo desde Clientes DNF +===================================== +Existen dos formas de utilizar el espejo comunitario en tus estaciones de trabajo y servidores: + +Opción recomendada: Conexión mediante nodo IPFS local +------------------------------------------------------ +Al contar con Kubo activo en tu equipo (escuchando en ``127.0.0.1:8080``), los paquetes se descargan por la red P2P. Si otro equipo en tu misma red de área local ya descargó una actualización, tu máquina la obtendrá a la velocidad del cable o wifi local sin salir a internet. + +Para Fedora (versiones 43, 44, 45 o Rawhide) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Crea el archivo ``/etc/yum.repos.d/fedora-mxos-ipfs.repo`` con privilegios administrativos: + +.. code-block:: ini + + [fedora-mxos-ipfs] + name=Fedora $releasever - $basearch (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/fedora/releases/$releasever/Everything/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch + + [fedora-updates-mxos-ipfs] + name=Fedora $releasever Updates - $basearch (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/fedora/updates/$releasever/$basearch/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch + +Para CentOS Stream 10 +~~~~~~~~~~~~~~~~~~~~~ +Crea el archivo ``/etc/yum.repos.d/centos-stream-mxos-ipfs.repo``: + +.. code-block:: ini + + [cs10-baseos-mxos-ipfs] + name=CentOS Stream 10 - BaseOS (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/centos-stream/10-stream/BaseOS/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + + [cs10-appstream-mxos-ipfs] + name=CentOS Stream 10 - AppStream (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/centos-stream/10-stream/AppStream/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + +Opción estándar: Conexión HTTPS directa +--------------------------------------- +Si tu equipo no ejecuta un demonio IPFS, puedes configurar tus repositorios apuntando directamente al punto de entrada HTTPS: + +.. code-block:: ini + + [fedora-mxos-https] + name=Fedora $releasever - $basearch (MxOS HTTPS) + baseurl=https://mirrors.mx-os.mx/fedora/releases/$releasever/Everything/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch + +Guía para Operadores de Nodos Guardianes +======================================== +Los nodos guardianes son la columna vertebral de la red. Cualquier persona con una computadora de escritorio, servidor casero o máquina virtual puede unirse al enjambre y alojar partes del catálogo. + +Paso 1: Instalación de Kubo +--------------------------- +Kubo está empaquetado para Fedora y CentOS Stream en el repositorio Copr de MxOS: + +.. code-block:: bash + + sudo dnf copr enable renich/kubo + sudo dnf install kubo + +Paso 2: Inicialización y servicio systemd +---------------------------------------- +Se recomienda operar Kubo en modo usuario no privilegiado (rootless): + +.. code-block:: bash + + # Inicializar el almacén en ~/.ipfs + ipfs init + + # Habilitar e iniciar el servicio persistente de usuario + systemctl --user enable --now ipfs.service + +Paso 3: Apertura del puerto del enjambre en el cortafuegos +---------------------------------------------------------- +Para permitir que otros nodos descarguen bloques desde tu nodo, abre el puerto 4001: + +.. code-block:: bash + + sudo firewall-cmd --permanent --add-port=4001/tcp + sudo firewall-cmd --permanent --add-port=4001/udp + sudo firewall-cmd --reload + +Paso 4: Pineo granular por cuota de almacenamiento +-------------------------------------------------- +No necesitas descargar los cientos de gigabytes del espejo completo. Elige el nivel que mejor se adapte a tu capacidad: + +* **Nivel 1: Imágenes ISO de Fedora (~15 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/fedora/iso + +* **Nivel 2: Sistema Base de CentOS Stream 10 (~15 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/centos-stream/10-stream/BaseOS + +* **Nivel 3: Paquetería AppStream y Everything (~80 a 150 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/fedora/releases/44/Everything + ipfs pin add /ipns/mirrors.mx-os.mx/centos-stream/10-stream/AppStream + +* **Nivel 4: Espejo maestro completo (~300 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx + +Estructura del Catálogo Canónico +================================ +El árbol publicado bajo ``/ipns/mirrors.mx-os.mx`` respeta rigurosamente las convenciones de rutas de Fedora y CentOS Stream: + +.. code-block:: text + + mirrors.mx-os.mx/ + ├── README.rst <- Documento de bienvenida e instrucciones + ├── fedora/ + │ ├── iso/ <- Imágenes de instalación de Fedora + │ ├── releases/ <- Árbol Everything por versión y arquitectura + │ └── updates/ <- Repositorios de actualizaciones continuas + └── centos-stream/ + ├── iso/ <- Medios de instalación de CentOS Stream + └── 10-stream/ + ├── BaseOS/ <- Paquetes base y núcleo del sistema + ├── AppStream/ <- Módulos y aplicaciones adicionales + └── CRB/ <- CodeReady Linux Builder + +Seguridad e Integridad Criptográfica +==================================== +La seguridad en la red de espejos descansa en dos barreras independientes e infranqueables: + +1. **Integridad de bloques:** La naturaleza direccionada por contenido de IPFS garantiza que ningún bit pueda alterarse en tránsito; si un bloque difiere de su hash, el cliente lo descarta automáticamente. +2. **Firmas GPG oficiales:** El gestor DNF valida cada RPM contra la llave pública oficial del proyecto correspondiente (ubicada en ``/etc/pki/rpm-gpg/``). Ni los operadores de nodos ni atacantes intermedios pueden inyectar código no firmado. + +Herramientas y Automatización en este Repositorio +================================================ +Este repositorio contiene los scripts de gestión y automatización de la infraestructura: + +* `bin/mxos-mirror-sync.bash`_: Sincronización diferencial upstream mediante rsync preservando metadatos. +* `bin/mxos-mirror-ingest.bash`_: Ingesta UnixFS en Kubo con soporte de filestore (``--nocopy``). +* `bin/mxos-dnslink-update.bash`_: Actualización desatendida del registro DNSLink en Cloudflare mediante API REST. +* `bin/mxos-mirror.bash`_: Orquestador integral del ciclo completo (sincronizar, ingerir y publicar). +* `etc/caddy/Caddyfile`_: Plantilla de proxy inverso para Caddy. +* `etc/nginx/mirrors.mx-os.mx.conf`_: Plantilla de configuración para Nginx. +* `systemd/`_: Unidades de servicio y temporizadores de systemd para tareas programadas. + +.. _bin/mxos-mirror-sync.bash: bin/mxos-mirror-sync.bash +.. _bin/mxos-mirror-ingest.bash: bin/mxos-mirror-ingest.bash +.. _bin/mxos-dnslink-update.bash: bin/mxos-dnslink-update.bash +.. _bin/mxos-mirror.bash: bin/mxos-mirror.bash +.. _etc/caddy/Caddyfile: etc/caddy/Caddyfile +.. _etc/nginx/mirrors.mx-os.mx.conf: etc/nginx/mirrors.mx-os.mx.conf +.. _systemd/: systemd/ + +Documentación Técnica Detallada +=============================== +Para profundizar en las especificaciones y manuales, consulta el directorio `docs/`_: + +* `docs/index.rst`_: Índice general de la documentación. +* `docs/business/spec.rst`_: Modelo estratégico, justificación e incentivos comunitarios. +* `docs/functional/spec.rst`_: Especificación de catálogo modular, pineo y telemetría pasiva. +* `docs/technical/spec.rst`_: Arquitectura de red, resolución DNSLink y puente MirrorManager. +* `docs/guides/index.rst`_: Manuales paso a paso para operadores, clientes y replicación autónoma. +* `docs/project/roadmap.rst`_: Fases de ejecución y seguimiento del proyecto. + +.. _docs/: docs/ +.. _docs/index.rst: docs/index.rst +.. _docs/business/spec.rst: docs/business/spec.rst +.. _docs/functional/spec.rst: docs/functional/spec.rst +.. _docs/technical/spec.rst: docs/technical/spec.rst +.. _docs/guides/index.rst: docs/guides/index.rst +.. _docs/project/roadmap.rst: docs/project/roadmap.rst + +Canales de Comunidad y Contacto +=============================== +* **Canal oficial de Telegram:** `@mx_os_mx`_ +* **Sitio web:** `mx-os.mx`_ +* **Repositorios de código:** `git.mx-os.mx`_ + +.. _@mx_os_mx: https://t.me/mx_os_mx +.. _mx-os.mx: https://mx-os.mx +.. _git.mx-os.mx: https://git.mx-os.mx + +Licenciamiento +============== +Este proyecto opera bajo un modelo de licenciamiento dual: + +* **Documentación y especificaciones:** Licenciadas bajo `Creative Commons Atribución-CompartirIgual 4.0 Internacional`_ (CC-BY-SA-4.0). +* **Herramientas, scripts y configuraciones:** Licenciadas bajo la `Licencia MIT`_. + +.. _Creative Commons Atribución-CompartirIgual 4.0 Internacional: https://creativecommons.org/licenses/by-sa/4.0/ +.. _Licencia MIT: https://opensource.org/license/mit diff --git a/bin/mxos-dnslink-update.bash b/bin/mxos-dnslink-update.bash new file mode 100755 index 0000000..e18147f --- /dev/null +++ b/bin/mxos-dnslink-update.bash @@ -0,0 +1,118 @@ +#!/usr/bin/bash +set -euo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +# Cargar configuración si existe +if [[ -f "${REPO_ROOT}/etc/mirrors.env" ]]; then + # shellcheck source=/dev/null + source "${REPO_ROOT}/etc/mirrors.env" +fi + +CF_ZONE_ID="${CF_ZONE_ID:-2bd35b00a854bc77cfd38009f977ea3c}" +MIRRORS_DNSLINK_RECORD="${MIRRORS_DNSLINK_RECORD:-_dnslink.mirrors.mx-os.mx}" + +resolve_cf_token() { + if [[ -n "${CF_API_TOKEN:-}" ]]; then + echo "${CF_API_TOKEN}" + return 0 + fi + + if command -v gopass >/dev/null 2>&1; then + local token + token="$(gopass show -f cloudflare.com/renich@evalinux.com 2>/dev/null | awk '/^API Token:/ {print $3}' | tr -d '[:space:]')" + if [[ -n "${token}" ]]; then + echo "${token}" + return 0 + fi + fi + + echo "Error: No se encontró token de Cloudflare en CF_API_TOKEN ni en GoPass." >&2 + return 1 +} + +update_or_create_dnslink() { + local token="$1" + local record_name="$2" + local cid="$3" + local dnslink_content="dnslink=/ipfs/${cid}" + + echo "==> Actualizando registro DNSLink para ${record_name}..." + + # Buscar si el registro ya existe + local search_response + search_response="$(curl -4 --max-time 15 -s -X GET \ + "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records?type=TXT&name=${record_name}" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json")" + + local record_id + record_id="$(echo "${search_response}" | jq -r '.result[0].id // empty')" + + if [[ -n "${record_id}" ]]; then + local update_response + update_response="$(curl -4 --max-time 15 -s -X PUT \ + "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records/${record_id}" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json" \ + -d "{\"type\":\"TXT\",\"name\":\"${record_name}\",\"content\":\"${dnslink_content}\",\"ttl\":300}")" + + if echo "${update_response}" | jq -e '.success' >/dev/null 2>&1; then + echo " Registro ${record_name} actualizado exitosamente -> ${dnslink_content}" + else + echo "Error actualizando registro ${record_name}:" >&2 + echo "${update_response}" | jq .errors >&2 + return 1 + fi + else + local create_response + create_response="$(curl -4 --max-time 15 -s -X POST \ + "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records" \ + -H "Authorization: Bearer ${token}" \ + -H "Content-Type: application/json" \ + -d "{\"type\":\"TXT\",\"name\":\"${record_name}\",\"content\":\"${dnslink_content}\",\"ttl\":300}")" + + if echo "${create_response}" | jq -e '.success' >/dev/null 2>&1; then + echo " Registro ${record_name} creado exitosamente -> ${dnslink_content}" + else + echo "Error creando registro ${record_name}:" >&2 + echo "${create_response}" | jq .errors >&2 + return 1 + fi + fi +} + +main() { + local target_cid="${1:-}" + + if [[ -z "${target_cid}" ]]; then + if [[ ! -t 0 ]]; then + read -r target_cid + fi + fi + + if [[ -z "${target_cid}" ]]; then + echo "Uso: $0 " >&2 + echo " O pase el CID por tubería estándar: echo \$CID | $0" >&2 + exit 1 + fi + + # Limpiar prefijo si viene con /ipfs/ + target_cid="${target_cid#/ipfs/}" + + local token + token="$(resolve_cf_token)" + + update_or_create_dnslink "${token}" "${MIRRORS_DNSLINK_RECORD}" "${target_cid}" + + echo "==> Verificando resolución DNSLink canónica..." + if command -v ipfs >/dev/null 2>&1; then + local resolved + resolved="$(ipfs resolve "/ipns/${MIRRORS_DOMAIN}" 2>/dev/null || true)" + echo " IPFS resolve /ipns/${MIRRORS_DOMAIN} -> ${resolved:-pendiente de propagación}" + fi +} + +main "$@" diff --git a/bin/mxos-mirror-ingest.bash b/bin/mxos-mirror-ingest.bash new file mode 100755 index 0000000..2fd99f3 --- /dev/null +++ b/bin/mxos-mirror-ingest.bash @@ -0,0 +1,92 @@ +#!/usr/bin/bash +set -euo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +if [[ -f "${REPO_ROOT}/etc/mirrors.env" ]]; then + # shellcheck source=/dev/null + source "${REPO_ROOT}/etc/mirrors.env" +fi + +MIRRORS_STAGING_DIR="${MIRRORS_STAGING_DIR:-$HOME/.local/share/mxos-mirrors/staging}" +IPFS_USE_NOCOPY="${IPFS_USE_NOCOPY:-false}" + +log() { + local level="$1" + shift + local timestamp + timestamp="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + echo "{\"timestamp\":\"${timestamp}\",\"level\":\"${level}\",\"message\":\"$*\"}" +} + +usage() { + cat << USAGE +Uso: $0 [OPCIONES] [DIRECTORIO_STAGING] + +Ingesta el directorio de staging en Kubo (IPFS) generando el grafo UnixFS DAG y retornando el CID raíz. + +Opciones: + --nocopy Utiliza la extensión filestore (--nocopy) para evitar duplicación en disco + -h, --help Muestra este mensaje de ayuda +USAGE + exit 1 +} + +main() { + local use_nocopy="${IPFS_USE_NOCOPY}" + local staging_dir="${MIRRORS_STAGING_DIR}" + + while [[ $# -gt 0 ]]; do + case "$1" in + --nocopy) + use_nocopy="true" + shift + ;; + -h|--help) + usage + ;; + *) + staging_dir="$1" + shift + ;; + esac + done + + if [[ ! -d "${staging_dir}" ]]; then + log "ERROR" "Directorio de staging no encontrado: ${staging_dir}" >&2 + exit 1 + fi + + # Asegurar que README.rst esté presente en la raíz + if [[ -f "${REPO_ROOT}/README.rst" && ! -f "${staging_dir}/README.rst" ]]; then + cp "${REPO_ROOT}/README.rst" "${staging_dir}/README.rst" + fi + + log "INFO" "Iniciando ingesta UnixFS de ${staging_dir} en Kubo..." + + local ipfs_args=(add -r --cid-version=1 --hash=sha2-256 -Q) + + if [[ "${use_nocopy}" == "true" ]]; then + ipfs_args+=(--nocopy) + fi + + local root_cid + root_cid="$(ipfs "${ipfs_args[@]}" "${staging_dir}")" + + if [[ -z "${root_cid}" ]]; then + log "ERROR" "Fallo en la generación del CID raíz." >&2 + exit 1 + fi + + log "INFO" "Ingesta completada exitosamente. CID raíz: ${root_cid}" + + # Asegurar pineo local del nuevo CID + ipfs pin add "${root_cid}" >/dev/null 2>&1 || true + + # Salida limpia del CID por stdout + echo "${root_cid}" +} + +main "$@" diff --git a/bin/mxos-mirror-sync.bash b/bin/mxos-mirror-sync.bash new file mode 100755 index 0000000..5367b2d --- /dev/null +++ b/bin/mxos-mirror-sync.bash @@ -0,0 +1,159 @@ +#!/usr/bin/bash +set -euo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +if [[ -f "${REPO_ROOT}/etc/mirrors.env" ]]; then + # shellcheck source=/dev/null + source "${REPO_ROOT}/etc/mirrors.env" +fi + +MIRRORS_STAGING_DIR="${MIRRORS_STAGING_DIR:-$HOME/.local/share/mxos-mirrors/staging}" +MIRRORS_LOG_DIR="${MIRRORS_LOG_DIR:-$HOME/.local/share/mxos-mirrors/logs}" +FEDORA_UPSTREAM_RSYNC="${FEDORA_UPSTREAM_RSYNC:-rsync://dl.fedoraproject.org/pub/fedora/linux}" +CENTOS_UPSTREAM_RSYNC="${CENTOS_UPSTREAM_RSYNC:-rsync://mirror.stream.centos.org/centos-stream}" + +log() { + local level="$1" + shift + local timestamp + timestamp="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + echo "{\"timestamp\":\"${timestamp}\",\"level\":\"${level}\",\"message\":\"$*\"}" +} + +usage() { + cat << USAGE +Uso: $0 [OPCIONES] + +Sincroniza repositorios oficiales de software libre hacia el directorio de staging local. + +Opciones: + -d, --distro Distribución a sincronizar (predeterminado: all) + -n, --dry-run Simula la sincronización sin transferir datos + -t, --target Directorio de destino de staging (predeterminado: ${MIRRORS_STAGING_DIR}) + -h, --help Muestra este mensaje de ayuda +USAGE + exit 1 +} + +sync_fedora() { + local target_dir="$1" + local dry_run_flag="$2" + local fedora_target="${target_dir}/fedora" + + log "INFO" "Iniciando sincronización de Fedora hacia ${fedora_target}..." + mkdir -p "${fedora_target}" + + # En modo prueba de concepto inicial, sincronizamos metadatos y estructura + local rsync_cmd=( + rsync -avSHP --delete-delay --delay-updates + --exclude="*.iso" + --exclude="*.raw.xz" + --exclude="debug/" + --exclude="source/" + --timeout=60 + ) + + if [[ "${dry_run_flag}" == "true" ]]; then + rsync_cmd+=("--dry-run") + fi + + rsync_cmd+=( + "${FEDORA_UPSTREAM_RSYNC}/releases/43/Everything/x86_64/os/repodata" + "${fedora_target}/releases/43/Everything/x86_64/os/" + ) + + log "INFO" "Ejecutando: ${rsync_cmd[*]}" + "${rsync_cmd[@]}" || log "WARN" "Sincronización parcial o simulada de Fedora." +} + +sync_centos() { + local target_dir="$1" + local dry_run_flag="$2" + local centos_target="${target_dir}/centos-stream" + + log "INFO" "Iniciando sincronización de CentOS Stream hacia ${centos_target}..." + mkdir -p "${centos_target}" + + local rsync_cmd=( + rsync -avSHP --delete-delay --delay-updates + --exclude="*.iso" + --exclude="debug/" + --exclude="source/" + --timeout=60 + ) + + if [[ "${dry_run_flag}" == "true" ]]; then + rsync_cmd+=("--dry-run") + fi + + rsync_cmd+=( + "${CENTOS_UPSTREAM_RSYNC}/10-stream/BaseOS/x86_64/os/repodata" + "${centos_target}/10-stream/BaseOS/x86_64/os/" + ) + + log "INFO" "Ejecutando: ${rsync_cmd[*]}" + "${rsync_cmd[@]}" || log "WARN" "Sincronización parcial o simulada de CentOS Stream." +} + +sync_readme() { + local target_dir="$1" + log "INFO" "Copiando README.rst canónico hacia la raíz de staging..." + cp "${REPO_ROOT}/README.rst" "${target_dir}/README.rst" +} + +main() { + local distro="all" + local dry_run="false" + local target="${MIRRORS_STAGING_DIR}" + + while [[ $# -gt 0 ]]; do + case "$1" in + -d|--distro) + distro="$2" + shift 2 + ;; + -n|--dry-run) + dry_run="true" + shift + ;; + -t|--target) + target="$2" + shift 2 + ;; + -h|--help) + usage + ;; + *) + echo "Opción desconocida: $1" >&2 + usage + ;; + esac + done + + mkdir -p "${target}" "${MIRRORS_LOG_DIR}" + sync_readme "${target}" + + case "${distro}" in + fedora) + sync_fedora "${target}" "${dry_run}" + ;; + centos) + sync_centos "${target}" "${dry_run}" + ;; + all) + sync_fedora "${target}" "${dry_run}" + sync_centos "${target}" "${dry_run}" + ;; + *) + echo "Distribución no válida: ${distro}" >&2 + exit 1 + ;; + esac + + log "INFO" "Sincronización upstream finalizada exitosamente." +} + +main "$@" diff --git a/bin/mxos-mirror.bash b/bin/mxos-mirror.bash new file mode 100755 index 0000000..181a84a --- /dev/null +++ b/bin/mxos-mirror.bash @@ -0,0 +1,141 @@ +#!/usr/bin/bash +set -euo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +if [[ -f "${REPO_ROOT}/etc/mirrors.env" ]]; then + # shellcheck source=/dev/null + source "${REPO_ROOT}/etc/mirrors.env" +fi + +MIRRORS_STAGING_DIR="${MIRRORS_STAGING_DIR:-$HOME/.local/share/mxos-mirrors/staging}" +MIRRORS_DOMAIN="${MIRRORS_DOMAIN:-mirrors.mx-os.mx}" + +usage() { + cat << USAGE +Uso: $0 [OPCIONES] + +Herramienta de orquestación de la Red de Espejos Comunitarios de MxOS. + +Comandos: + sync Sincroniza paquetes y metadatos upstream hacia el directorio de staging + ingest Ingesta el directorio de staging en Kubo generando el CID raíz + publish Actualiza el registro DNSLink en Cloudflare con un CID específico + run-all Ejecuta el flujo completo: sincronizar, ingerir y publicar en DNSLink + status Muestra el estado de resolución, demonio IPFS y registro DNSLink + replicate Replica el CID raíz actual hacia el nodo público web0.mx-os.mx + help Muestra este mensaje de ayuda +USAGE + exit 1 +} + +cmd_status() { + echo "==========================================================" + echo " Estado de la Red de Espejos MxOS (${MIRRORS_DOMAIN})" + echo "==========================================================" + + echo -n "1. Demonio IPFS local: " + if command -v ipfs >/dev/null 2>&1 && ipfs id >/dev/null 2>&1; then + local peer_id + peer_id="$(ipfs id -f='\n')" + echo "Activo (PeerID: ${peer_id})" + else + echo "Inactivo o no instalado" + fi + + echo -n "2. Registro DNSLink en Cloudflare (_dnslink.${MIRRORS_DOMAIN}): " + local dns_val + dns_val="$(dig +short TXT "_dnslink.${MIRRORS_DOMAIN}" @1.1.1.1 2>/dev/null || echo "No resoluble")" + echo "${dns_val:-Sin registro}" + + echo -n "3. Resolución canónica IPFS (/ipns/${MIRRORS_DOMAIN}): " + if command -v ipfs >/dev/null 2>&1; then + local ipns_val + ipns_val="$(ipfs resolve "/ipns/${MIRRORS_DOMAIN}" 2>/dev/null || echo "Error de resolución")" + echo "${ipns_val}" + else + echo "No disponible (sin cliente ipfs)" + fi + + echo -n "4. Punto final HTTPS público (https://${MIRRORS_DOMAIN}/): " + local http_code + http_code="$(curl -s -o /dev/null -w "%{http_code}" "https://${MIRRORS_DOMAIN}/" 2>/dev/null || echo "Fallo de conexión")" + echo "Código HTTP ${http_code}" + echo "==========================================================" +} + +cmd_replicate() { + local target_cid="${1:-}" + + if [[ -z "${target_cid}" ]]; then + target_cid="$(ipfs resolve "/ipns/${MIRRORS_DOMAIN}" 2>/dev/null || true)" + target_cid="${target_cid#/ipfs/}" + fi + + if [[ -z "${target_cid}" ]]; then + echo "Error: No se pudo determinar el CID raíz a replicar." >&2 + exit 1 + fi + + echo "==> Replicando DAG ${target_cid} hacia web0.mx-os.mx..." + # shellcheck disable=SC2029 + ipfs dag export "${target_cid}" | ssh root@web0.mx-os.mx \ + "ipfs --api=/ip4/127.0.0.1/tcp/5001 dag import && ipfs --api=/ip4/127.0.0.1/tcp/5001 pin add ${target_cid}" + echo "==> Replicación completada con éxito en web0." +} + +cmd_run_all() { + echo "==> [Paso 1/4] Sincronización upstream..." + "${SCRIPT_DIR}/mxos-mirror-sync.bash" + + echo "==> [Paso 2/4] Ingesta UnixFS en Kubo..." + local root_cid + root_cid="$("${SCRIPT_DIR}/mxos-mirror-ingest.bash")" + echo " Nuevo CID raíz: ${root_cid}" + + echo "==> [Paso 3/4] Publicación en DNSLink Cloudflare..." + "${SCRIPT_DIR}/mxos-dnslink-update.bash" "${root_cid}" + + echo "==> [Paso 4/4] Replicación hacia nodo público web0..." + cmd_replicate "${root_cid}" + + echo "==> Flujo completado exitosamente." + cmd_status +} + +main() { + local cmd="${1:-}" + shift || true + + case "${cmd}" in + sync) + "${SCRIPT_DIR}/mxos-mirror-sync.bash" "$@" + ;; + ingest) + "${SCRIPT_DIR}/mxos-mirror-ingest.bash" "$@" + ;; + publish) + "${SCRIPT_DIR}/mxos-dnslink-update.bash" "$@" + ;; + run-all) + cmd_run_all + ;; + status) + cmd_status + ;; + replicate) + cmd_replicate "$@" + ;; + help|--help|-h|"") + usage + ;; + *) + echo "Comando desconocido: ${cmd}" >&2 + usage + ;; + esac +} + +main "$@" diff --git a/docs/business/spec.rst b/docs/business/spec.rst new file mode 100644 index 0000000..5c7a3fc --- /dev/null +++ b/docs/business/spec.rst @@ -0,0 +1,18 @@ +================================== +Especificación de Negocio y Misión +================================== + +Visión General +============== +La distribución tradicional de software libre enfrenta una creciente centralización en redes de entrega de contenido (CDNs) comerciales y una pesada carga financiera de transferencia de datos para los espejos universitarios y comunitarios. En México, la ausencia histórica de un espejo primario local para Fedora y CentOS Stream obliga a que cada instalación y actualización transite por enlaces internacionales hacia servidores en Estados Unidos. + +La iniciativa de espejos de MxOS replantea este modelo utilizando el Sistema de Archivos Interplanetario (IPFS) para conformar una red de guerrilla donde cualquier persona u organización puede aportar almacenamiento local y ancho de banda, democratizando la infraestructura y blindándola contra fallos o censura. + +Documentos del Dominio +====================== + +.. toctree:: + :maxdepth: 1 + + specs/mision-vision + specs/incentivos-comunidad diff --git a/docs/business/specs/incentivos-comunidad.rst b/docs/business/specs/incentivos-comunidad.rst new file mode 100644 index 0000000..26f824b --- /dev/null +++ b/docs/business/specs/incentivos-comunidad.rst @@ -0,0 +1,27 @@ +==================================== +Modelo de Participación e Incentivos +==================================== + +Filosofía de Participación +========================== +La participación en la red de espejos de MxOS es voluntaria, descentralizada y respetuosa de la privacidad. No se requiere registro obligatorio de cuentas ni instalación de agentes de telemetría invasivos para formar parte del enjambre. + +Incentivos para Colaboradores +============================= +Para reconocer el esfuerzo de quienes donan almacenamiento, electricidad y ancho de banda, MxOS establece los siguientes mecanismos: + +Salón de Guardianes del Espejo +------------------------------ +* **Reconocimiento público opcional:** Los operadores de nodos que decidan asociar voluntariamente su identificador de nodo (PeerID) con su perfil de la comunidad o GitLab aparecerán en el tablero de honor de ``mirrors.mx-os.mx``. +* **Insignias y trazabilidad:** Distinciones honoríficas basadas en la constancia del nodo en el enjambre y el nivel de repositorios respaldados. + +Servicios de Red Comunitaria +---------------------------- +* **Subdominios comunitarios:** Operadores con nodos activos y verificados podrán solicitar subdominios personalizados bajo ``*.mx-os.mx`` para sus proyectos personales de software libre. +* **Prioridad de enrutamiento:** Listado público de pares recomendados para conexión directa (peering estático) entre nodos de MxOS dentro de puntos de intercambio de tráfico de internet (IXP) en México. + +Garantías de Privacidad +======================= +* El enjambre utiliza los mecanismos criptográficos nativos de libp2p y la tabla hash distribuida (DHT). +* La presencia del nodo se verifica mediante el anuncio público de bloques provistos (find providers). +* No se recopilan historiales de navegación, patrones de paquetes instalados por clientes individuales ni datos de hardware del usuario. diff --git a/docs/business/specs/mision-vision.rst b/docs/business/specs/mision-vision.rst new file mode 100644 index 0000000..3194975 --- /dev/null +++ b/docs/business/specs/mision-vision.rst @@ -0,0 +1,28 @@ +===================================== +Misión y Soberanía de Infraestructura +===================================== + +Contexto y Problemática +======================= +Las distribuciones de software libre dependen de redes geolocalizadas de servidores espejo para entregar paquetes y archivos de imagen a millones de computadoras. Este esquema adolece de problemas estructurales en economías en desarrollo: + +* **Asimetría de infraestructura:** México carece de un espejo oficial activo de Fedora o CentOS Stream en MirrorManager, dependiendo exclusivamente de enlaces transfronterizos. +* **Costo de transferencia insostenible:** Un espejo tradicional debe sincronizar petabytes mensuales mediante rsync y HTTP hacia miles de usuarios, requiriendo enlaces simétricos dedicados inaccesibles para comunidades pequeñas. +* **Desperdicio de ancho de banda:** Cientos de computadoras en la misma colonia, universidad o edificio de oficinas descargan de manera redundante los mismos paquetes de actualización desde servidores remotos. + +Misión de MxOS +============== +La Fundación MxOS impulsa la soberanía tecnológica en sistemas operativos. La misión de esta iniciativa consiste en: + +1. Desacoplar la distribución de software del direccionamiento por ubicación (servidores específicos) y migrarla al direccionamiento por contenido criptográfico mediante IPFS. +2. Permitir que cualquier persona con una laptop, servidor casero o almacenamiento conectado a red (NAS) se sume a la red de distribución según su capacidad de disco disponible. +3. Establecer el primer espejo comunitario federado de Fedora y CentOS Stream 10 en México, coordinado por la comunidad y auditado abiertamente. +4. Documentar y empaquetar todo el procedimiento para que cualquier otra comunidad pueda replicar espejos similares para cualquier proyecto de software libre. + +Impacto Regional +================ +La implementación de esta red produce tres beneficios inmediatos: + +* **Aceleración en red local:** En universidades y redes locales, un paquete caliente se descarga únicamente una vez desde la red externa; los siguientes equipos lo obtienen a velocidad de enlace local vía Bitswap. +* **Resiliencia ante caídas de enlace:** En caso de fallos en rutas internacionales o saturación de CDNs, los repositorios permanecen disponibles entre los pares locales. +* **Autonomía tecnológica:** Reduce la dependencia hacia infraestructura comercial privada sin sacrificar la verificación criptográfica oficial provista por las firmas GPG de los proyectos originales. diff --git a/docs/functional/spec.rst b/docs/functional/spec.rst new file mode 100644 index 0000000..9a55c93 --- /dev/null +++ b/docs/functional/spec.rst @@ -0,0 +1,26 @@ +======================== +Especificación Funcional +======================== + +Visión General +============== +Este documento define los requisitos funcionales del sistema de espejos comunitarios sobre IPFS. El sistema debe permitir la ingesta programada de paquetes desde fuentes oficiales, su publicación bajo un esquema de direccionamiento canónico, el pineo selectivo por parte de la comunidad y el consumo transparente desde clientes convencionales de Linux. + +Requisitos Funcionales del Sistema +================================== + +* **[FUNC-001] Ingesta y Catálogo Modular de Repositorios:** El sistema debe sincronizar y catalogar periódicamente los repositorios oficiales de Fedora y CentOS Stream 10 sin alterar sus metadatos ni firmas GPG. +* **[FUNC-002] Pineo Granular por Niveles:** El sistema debe permitir a los colaboradores almacenar y respaldar subárboles específicos según su disponibilidad de almacenamiento, sin obligar la descarga de la totalidad del espejo. +* **[FUNC-003] Publicación Canónica con DNSLink:** El sistema debe mantener una referencia mutable controlada bajo el dominio ``mirrors.mx-os.mx`` que apunte al identificador de contenido (CID) raíz más reciente. +* **[FUNC-004] Tablero de Métricas Públicas:** El sistema debe presentar un portal web público con estadísticas en tiempo real sobre nodos activos, volumen distribuido y mapa de distribución geográfica sin recolectar telemetría en el cliente. +* **[FUNC-005] Consumo Nativo en Clientes DNF:** El sistema debe posibilitar que cualquier instalación estándar de Fedora o CentOS Stream configure repositorios locales apuntando al gateway HTTP de IPFS. + +Documentos del Dominio +====================== + +.. toctree:: + :maxdepth: 1 + + specs/catalogo-modular + specs/pineo-granular + specs/tablero-metricas diff --git a/docs/functional/specs/catalogo-modular.rst b/docs/functional/specs/catalogo-modular.rst new file mode 100644 index 0000000..c34693e --- /dev/null +++ b/docs/functional/specs/catalogo-modular.rst @@ -0,0 +1,40 @@ +================================ +Catálogo Modular de Repositorios +================================ + +Identificador Funcional: [FUNC-001] + +Objetivo +======== +Definir la organización y jerarquía lógica de los archivos y repositorios servidos bajo la red comunitaria de espejos de MxOS, asegurando coherencia con los árboles estándar de Fedora y CentOS Stream. + +Estructura del Árbol Canónico +============================= +El árbol servido bajo ``/ipns/mirrors.mx-os.mx`` debe dividirse en ramas bien delimitadas por distribución, tipo de contenido y arquitectura: + +.. code-block:: text + + mirrors.mx-os.mx/ + ├── fedora/ + │ ├── iso/ + │ │ ├── 44/ + │ │ └── 45/ + │ ├── releases/ + │ │ ├── 44/Everything/x86_64/os/ + │ │ └── 45/Everything/x86_64/os/ + │ └── updates/ + │ ├── 44/x86_64/ + │ └── 45/x86_64/ + └── centos-stream/ + ├── iso/ + │ └── 10-stream/ + └── 10-stream/ + ├── BaseOS/x86_64/os/ + ├── AppStream/x86_64/os/ + └── CRB/x86_64/os/ + +Criterios de Aceptación +======================= +1. La estructura de directorios debe respetar estrictamente los nombres esperados por las variables ``$releasever`` y ``$basearch`` de DNF. +2. Los metadatos de repositorio (ejemplo: ``repodata/repomd.xml``) deben ser idénticos a los publicados por los servidores primarios upstream para garantizar la verificación de firmas criptográficas. +3. La sincronización upstream debe preservar atributos de tiempo y enlaces relativos para asegurar la validez de los paquetes. diff --git a/docs/functional/specs/pineo-granular.rst b/docs/functional/specs/pineo-granular.rst new file mode 100644 index 0000000..3b0be88 --- /dev/null +++ b/docs/functional/specs/pineo-granular.rst @@ -0,0 +1,34 @@ +================================ +Especificación de Pineo Granular +================================ + +Identificador Funcional: [FUNC-002] + +Objetivo +======== +Permitir que cualquier usuario o entidad colaboradora participe en la red de distribución respaldando únicamente una porción específica de los repositorios, adaptándose a sus restricciones de almacenamiento en disco. + +Niveles de Participación +======================== +El sistema clasifica el contenido en cuatro niveles de compromiso de almacenamiento: + +.. table:: Niveles de almacenamiento para colaboradores + :widths: auto + + +-------+-----------------------------+--------------------+-----------------------------+ + | Nivel | Contenido | Tamaño Aproximado | Perfil de Nodo Recomendado | + +=======+=============================+====================+=============================+ + | 1 | Imágenes ISO de instalación | 10 a 25 GB | Laptops, equipos personales | + +-------+-----------------------------+--------------------+-----------------------------+ + | 2 | Sistema Base (BaseOS) | 15 a 30 GB | Servidores caseros, mini PCs| + +-------+-----------------------------+--------------------+-----------------------------+ + | 3 | Distribución completa única | 80 a 150 GB | Servidores de oficina, labs | + +-------+-----------------------------+--------------------+-----------------------------+ + | 4 | Espejo integral (Todo) | 300+ GB | Servidores dedicados, NAS | + +-------+-----------------------------+--------------------+-----------------------------+ + +Comportamiento de Resolución +============================ +1. Cuando un colaborador solicita pinear una subruta (ejemplo: ``/ipns/mirrors.mx-os.mx/fedora/iso``), el demonio de IPFS debe resolver el CID específico de esa carpeta en el grafo UnixFS y aplicar el pin recursivo exclusivamente a dicho subnodo. +2. Los bloques ajenos a la subruta seleccionada no deben ser transferidos ni almacenados en el nodo local. +3. El proceso de sincronización debe reemplazar los pines anteriores cuando el CID de la subruta cambie, liberando espacio mediante recolección de basura si el usuario lo configura. diff --git a/docs/functional/specs/tablero-metricas.rst b/docs/functional/specs/tablero-metricas.rst new file mode 100644 index 0000000..08ca9e0 --- /dev/null +++ b/docs/functional/specs/tablero-metricas.rst @@ -0,0 +1,21 @@ +================================ +Tablero de Métricas del Enjambre +================================ + +Identificador Funcional: [FUNC-004] + +Objetivo +======== +Proporcionar visibilidad pública en tiempo real sobre el estado del enjambre de distribución, permitiendo a la comunidad auditar la disponibilidad de los repositorios y visualizar el crecimiento de la red. + +Requisitos del Tablero +====================== + +* **Descubrimiento descentralizado:** Las métricas de pares deben obtenerse consultando la tabla hash distribuida (DHT) de IPFS para los CIDs activos del catálogo, sin requerir que los nodos instalen software cliente adicional o transmitan telemetría privada. +* **Mapa de nodos:** Representación geográfica aproximada a nivel ciudad o estado basada en la resolución de direcciones IP públicas de los pares descubiertos. +* **Métricas visibles:** + * Número total de nodos proveedores activos en las últimas 24 horas. + * Volumen total estimado de almacenamiento distribuido en el enjambre. + * Desglose de disponibilidad por componente (ISOs, CentOS Stream 10, Fedora). + * Tiempo transcurrido desde la última sincronización upstream. +* **Transparencia y código abierto:** El código fuente completo del tablero debe residir en el repositorio público de Git de MxOS. diff --git a/docs/guides/cliente-dnf.rst b/docs/guides/cliente-dnf.rst new file mode 100644 index 0000000..d941c9a --- /dev/null +++ b/docs/guides/cliente-dnf.rst @@ -0,0 +1,68 @@ +====================================== +Configuración de Clientes DNF con IPFS +====================================== + +Propósito +========= +Este manual detalla cómo configurar el gestor de paquetes DNF en cualquier estación de trabajo o servidor local para consumir paquetes directamente desde el enjambre de IPFS a través del gateway HTTP local (puerto 8080). + +Ventajas +======== +* **Velocidad máxima:** Los paquetes que tú o tus vecinos de red local hayan pineado se descargan a la velocidad máxima de la interfaz local sin saturar tu conexión hacia internet. +* **Seguridad criptográfica íntegra:** Las firmas GPG oficiales de Fedora y CentOS Stream siguen siendo verificadas por DNF contra las llaves oficiales instaladas en ``/etc/pki/rpm-gpg/``. + +Configuración para Fedora +========================= +Crea un archivo de repositorio en ``/etc/yum.repos.d/fedora-mxos-ipfs.repo`` con el siguiente contenido: + +.. code-block:: ini + + [fedora-mxos-ipfs] + name=Fedora $releasever - $basearch (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/fedora/releases/$releasever/Everything/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch + + [fedora-updates-mxos-ipfs] + name=Fedora $releasever Updates - $basearch (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/fedora/updates/$releasever/$basearch/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch + +Configuración para CentOS Stream 10 +=================================== +Crea un archivo en ``/etc/yum.repos.d/centos-stream-mxos-ipfs.repo``: + +.. code-block:: ini + + [cs10-baseos-mxos-ipfs] + name=CentOS Stream 10 - BaseOS (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/centos-stream/10-stream/BaseOS/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + + [cs10-appstream-mxos-ipfs] + name=CentOS Stream 10 - AppStream (Espejo MxOS IPFS) + baseurl=http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/centos-stream/10-stream/AppStream/$basearch/os/ + enabled=1 + metadata_expire=6h + gpgcheck=1 + gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial + +Prueba de Funcionamiento +======================== +Limpia la caché de metadatos de DNF y verifica la comunicación con el gateway local: + +.. code-block:: bash + + # Limpiar cachés previas + sudo dnf clean all --disablerepo="*" --enablerepo="*-mxos-ipfs" + + # Comprobar la actualización de metadatos + sudo dnf check-update --disablerepo="*" --enablerepo="*-mxos-ipfs" diff --git a/docs/guides/hazlo-tu-mismo.rst b/docs/guides/hazlo-tu-mismo.rst new file mode 100644 index 0000000..6572593 --- /dev/null +++ b/docs/guides/hazlo-tu-mismo.rst @@ -0,0 +1,73 @@ +=========================================== +Manual de Autonomía Técnica: Hazlo Tú Mismo +=========================================== + +Propósito y Filosofía +===================== +La misión fundamental de la Fundación MxOS no es monopolizar la distribución, sino transferir el conocimiento y capacitar a cualquier comunidad, escuela o empresa para que construya y opere su propia infraestructura de distribución soberana de software libre. + +Este manual documenta el procedimiento completo para levantar un espejo de guerrilla sobre IPFS para cualquier proyecto o distribución desde cero. + +Arquitectura Mínima Requerida +============================= +Para operar tu propio espejo primario necesitas: + +1. Un servidor con almacenamiento adecuado para el conjunto de paquetes a respaldar. +2. Demonio Kubo instalado y configurado con la extensión filestore. +3. Un dominio propio con control sobre los registros DNS autoritativos para configurar DNSLink. +4. Servidor web (Caddy, Nginx o Apache) para proporcionar terminación TLS y proxy inverso. + +Procedimiento Paso a Paso +========================= + +1. Configuración de Filestore en Kubo +------------------------------------- +Por defecto, agregar archivos a IPFS duplica su tamaño al copiarlos al almacén de bloques. Para evitar este desperdicio masivo de disco al sincronizar repositorios de cientos de gigabytes, habilita el filestore en la configuración de Kubo: + +.. code-block:: bash + + # Detener el servicio antes de modificar la configuración + systemctl --user stop ipfs.service + + # Habilitar filestore y experimental nocopy + ipfs config --json Experimental.FilestoreEnabled true + + # Iniciar nuevamente el servicio + systemctl --user start ipfs.service + +2. Sincronización Upstream con rsync +------------------------------------ +Descarga los paquetes desde el espejo oficial más cercano hacia un directorio local (ejemplo: ``/srv/mirrors/debian/`` o ``/srv/mirrors/archlinux/``): + +.. code-block:: bash + + rsync -avSHP --delete-delay \ + rsync://espejo.upstream.org/repositorio/ \ + /srv/mirrors/mi-proyecto/ + +3. Ingesta por Referencia (nocopy) +---------------------------------- +Genera el grafo UnixFS sin duplicar archivos en disco utilizando la opción ``--nocopy``: + +.. code-block:: bash + + CID=$(ipfs add -r --nocopy --cid-version=1 --hash=sha2-256 -Q /srv/mirrors/mi-proyecto/) + echo "El nuevo CID raíz es: $CID" + +4. Publicación en el Dominio con DNSLink +---------------------------------------- +Accede al panel de control o servidor DNS autoritativo de tu dominio (ejemplo: ``tudominio.org``) y crea o actualiza el registro TXT para tu subdominio de espejos: + +.. code-block:: zone + + _dnslink.espejos.tudominio.org. 300 IN TXT "dnslink=/ipfs/" + +A partir de este momento, cualquier persona en el mundo puede resolver y pinear tu repositorio ejecutando: + +.. code-block:: bash + + ipfs pin add /ipns/espejos.tudominio.org + +5. Exposición Dual HTTP / IPFS +------------------------------ +Configura un proxy inverso que reciba las conexiones HTTP convencionales y las envíe al gateway local de IPFS en ``127.0.0.1:8080/ipns/espejos.tudominio.org/``. De este modo, los usuarios tradicionales pueden seguir consumiendo el repositorio vía HTTP/HTTPS mientras tú te beneficias del enjambre P2P de respaldo. diff --git a/docs/guides/index.rst b/docs/guides/index.rst new file mode 100644 index 0000000..a72d21c --- /dev/null +++ b/docs/guides/index.rst @@ -0,0 +1,17 @@ +================ +Manuales y Guías +================ + +Visión General +============== +Esta sección contiene manuales prácticos paso a paso para sumarse a la red comunitaria de espejos, configurar clientes locales de Fedora y CentOS Stream para consumir los repositorios desde IPFS, y replicar toda la infraestructura de distribución para otros proyectos de software libre. + +Índice de Manuales +================== + +.. toctree:: + :maxdepth: 1 + + operador-nodo + cliente-dnf + hazlo-tu-mismo diff --git a/docs/guides/operador-nodo.rst b/docs/guides/operador-nodo.rst new file mode 100644 index 0000000..222dec7 --- /dev/null +++ b/docs/guides/operador-nodo.rst @@ -0,0 +1,84 @@ +================================== +Guía del Operador de Nodo Guardián +================================== + +Propósito +========= +Este manual explica cómo configurar un nodo local de IPFS en Fedora o CentOS Stream para unirse al enjambre de MxOS y pinear selectivamente los repositorios oficiales según la cuota de disco que desees donar. + +Requisitos Previos +================== +* Fedora 43, 44, 45, Rawhide o CentOS Stream 10. +* Acceso a privilegios administrativos mediante ``sudo``. +* Espacio en disco libre según el nivel de almacenamiento elegido (desde 10 GB en adelante). + +Paso 1: Instalación de Kubo desde Copr +====================================== +Kubo se encuentra empaquetado para la familia de distribuciones Fedora y CentOS Stream en el repositorio Copr de MxOS: + +.. code-block:: bash + + sudo dnf copr enable renich/kubo + sudo dnf install kubo + +Paso 2: Inicialización e Inicio del Servicio +============================================ +Se recomienda ejecutar el demonio en modo usuario rootless gestionado por systemd: + +.. code-block:: bash + + # Inicializar el almacén local de IPFS en el directorio de usuario (~/.ipfs) + ipfs init + + # Habilitar e iniciar el servicio persistente de usuario + systemctl --user enable --now ipfs.service + + # Verificar que el servicio esté activo y funcionando + systemctl --user status ipfs.service + +Paso 3: Apertura de Puertos en el Cortafuegos +============================================= +Para que otros pares en internet y en tu red local puedan descargar bloques desde tu nodo, abre el puerto de escucha del enjambre (4001): + +.. code-block:: bash + + sudo firewall-cmd --permanent --add-port=4001/tcp + sudo firewall-cmd --permanent --add-port=4001/udp + sudo firewall-cmd --reload + +Paso 4: Pineo Granular por Nivel +================================ +Selecciona el comando correspondiente a la rama que tu almacenamiento permita respaldar: + +* **Nivel 1: Imágenes ISO de Fedora (~15 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/fedora/iso + +* **Nivel 2: Sistema Base de CentOS Stream 10 (~15 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/centos-stream/10-stream/BaseOS/x86_64/os + +* **Nivel 3: CentOS Stream 10 Completo (~75 GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx/centos-stream/10-stream + +* **Nivel 4: Espejo Completo de MxOS (300+ GB)** + + .. code-block:: bash + + ipfs pin add /ipns/mirrors.mx-os.mx + +Paso 5: Automatización de la Sincronización +=========================================== +Dado que los paquetes y metadatos se actualizan periódicamente en upstream, el CID raíz en DNSLink cambiará. + +Para mantener tus pines al día: +1. Resuelve periódicamente la subruta deseada con ``ipfs resolve -r /ipns/mirrors.mx-os.mx/``. +2. Aplica el nuevo pin y retira el pin anterior. +3. Puedes programar este refresco mediante un temporizador de systemd en tu sesión de usuario (``~/.config/systemd/user/mxos-sync.timer``). diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..b258583 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,19 @@ +============================================= +Documentación de Espejos Comunitarios de MxOS +============================================= + +Bienvenido a la documentación maestra de la iniciativa de espejos de software libre sobre IPFS de la Fundación MxOS. + +Este compendio detalla los principios de diseño, especificaciones funcionales y técnicas, manuales de adopción y la hoja de ruta para operar una red de distribución por pares resiliente para Fedora, CentOS Stream y proyectos afines en México y la región. + +Contenido +========= + +.. toctree:: + :maxdepth: 2 + + business/spec + functional/spec + technical/spec + guides/index + project/roadmap diff --git a/docs/project/roadmap.rst b/docs/project/roadmap.rst new file mode 100644 index 0000000..0f4b369 --- /dev/null +++ b/docs/project/roadmap.rst @@ -0,0 +1,38 @@ +==================================== +Hoja de Ruta del Proyecto de Espejos +==================================== + +Visión General +============== +Esta hoja de ruta establece la secuencia cronológica de ejecución para implementar, validar, publicar y federar la red comunitaria de espejos sobre IPFS de la Fundación MxOS. + +El plan se divide en tres fases secuenciales regidas por dependencias estrictas y trazabilidad directa hacia las especificaciones funcionales y técnicas del proyecto. + +Fases de Ejecución +================== + +.. toctree:: + :maxdepth: 1 + + roadmaps/fase-1-poc + roadmaps/fase-2-tablero + roadmaps/fase-3-federacion-upstream + +Matriz de Fases y Entregables +============================= + +.. table:: Resumen de fases del proyecto + :widths: auto + + +-------+------------------------------------+--------------------------+-----------------------+ + | Fase | Denominación | Entregable Principal | Dependencia Crítica | + +=======+====================================+==========================+=======================+ + | 1 | Prueba de Concepto y Publicación | Nodo servidor operativo, | Dominio DNSLink y | + | | Canónica | DNSLink y sync inicial | paquete Copr de Kubo | + +-------+------------------------------------+--------------------------+-----------------------+ + | 2 | Tablero de Métricas del Enjambre | Portal público web con | Nodos proveedores | + | | | mapa y conteo de nodos | activos en la DHT | + +-------+------------------------------------+--------------------------+-----------------------+ + | 3 | Federacion e Integración Upstream | Registro en MirrorManager| Estabilidad de Fase 1 | + | | | y RFC en listas upstream | y Fase 2 demostrada | + +-------+------------------------------------+--------------------------+-----------------------+ diff --git a/docs/project/roadmaps/fase-1-poc.rst b/docs/project/roadmaps/fase-1-poc.rst new file mode 100644 index 0000000..84ed837 --- /dev/null +++ b/docs/project/roadmaps/fase-1-poc.rst @@ -0,0 +1,45 @@ +================================================= +Fase 1: Prueba de Concepto y Publicación Canónica +================================================= + +Objetivo +======== +Validar de punta a punta la ingesta, generación de DAGs UnixFS, actualización de registros DNSLink y resolución de subrutas para Fedora y CentOS Stream 10 bajo ``mirrors.mx-os.mx``. + +Trazabilidad: [FUNC-001], [FUNC-002], [FUNC-003], [TECH-001], [TECH-002], [TECH-003] + +Hitos de la Fase +================ + +Hito 1.1: Aprovisionamiento del Nodo Cabecera de MxOS +----------------------------------------------------- +Poner en marcha el entorno de almacenamiento y el demonio Kubo en la infraestructura de servidores de la Fundación MxOS. + +* **Tarea 1.1.1 [TECH-001]:** Configurar el directorio de staging en el servidor y habilitar la extensión filestore en Kubo. + * *Bloqueado por:* Ninguno. + * *Desbloquea:* Tarea 1.1.2. +* **Tarea 1.1.2 [TECH-001]:** Ejecutar la sincronización rsync inicial de imágenes ISO de Fedora y el repositorio BaseOS de CentOS Stream 10. + * *Bloqueado por:* Tarea 1.1.1. + * *Desbloquea:* Tarea 1.1.3. +* **Tarea 1.1.3 [TECH-001]:** Realizar la ingesta por referencia con ``ipfs add -r --nocopy`` y verificar la integridad de los CIDs generados. + * *Bloqueado por:* Tarea 1.1.2. + * *Desbloquea:* Tarea 1.2.1. + +Hito 1.2: Configuración de DNSLink y Validación de Subrutas +----------------------------------------------------------- +Establecer la delegación DNS inmutable y verificar la granularidad del enjambre. + +* **Tarea 1.2.1 [TECH-003]:** Crear el registro TXT ``_dnslink.mirrors.mx-os.mx`` con el CID raíz de la ingesta. + * *Bloqueado por:* Tarea 1.1.3. + * *Desbloquea:* Tarea 1.2.2. +* **Tarea 1.2.2 [TECH-002]:** Validar la resolución y pineo recursivo exclusivo de subrutas (ejemplo: ``/ipns/mirrors.mx-os.mx/centos-stream/10-stream/BaseOS``) desde un nodo cliente externo. + * *Bloqueado por:* Tarea 1.2.1. + * *Desbloquea:* Hito 1.3. + +Hito 1.3: Redacción del Post Inicial en el Sitio de MxOS +-------------------------------------------------------- +Publicar el artículo de presentación en ``mx-os.mx`` y convocar a los primeros operadores guardianes. + +* **Tarea 1.3.1 [FUNC-003]:** Redactar y publicar el artículo de lanzamiento en la web de MxOS enlazando al manual de operadores. + * *Bloqueado por:* Tarea 1.2.2. + * *Desbloquea:* Fase 2. diff --git a/docs/project/roadmaps/fase-2-tablero.rst b/docs/project/roadmaps/fase-2-tablero.rst new file mode 100644 index 0000000..ba60ea9 --- /dev/null +++ b/docs/project/roadmaps/fase-2-tablero.rst @@ -0,0 +1,42 @@ +======================================== +Fase 2: Tablero de Métricas del Enjambre +======================================== + +Objetivo +======== +Desarrollar, empaquetar y desplegar el portal web público de estadísticas en tiempo real y mapa de nodos distribuido, publicado como software libre en el repositorio de Git de MxOS. + +Trazabilidad: [FUNC-004], [TECH-004] + +Hitos de la Fase +================ + +Hito 2.1: Motor de Recolección Descentralizada +---------------------------------------------- +Crear el servicio en segundo plano que sondea la DHT para identificar los nodos activos. + +* **Tarea 2.1.1 [TECH-004]:** Implementar el colector pasivo que consulta periódicamente ``ipfs dht findprovs`` para los CIDs activos del espejo. + * *Bloqueado por:* Fase 1 (Tarea 1.2.2). + * *Desbloquea:* Tarea 2.1.2. +* **Tarea 2.1.2 [TECH-004]:** Integrar la base de datos local MaxMind GeoLite2 para resolver la geolocalización aproximada (país y estado) sin almacenar direcciones IP completas. + * *Bloqueado por:* Tarea 2.1.1. + * *Desbloquea:* Hito 2.2. + +Hito 2.2: Interfaz Web Pública Reactiva +--------------------------------------- +Construir el portal web ligero de visualización para la comunidad. + +* **Tarea 2.2.1 [FUNC-004]:** Diseñar la interfaz con mapa interactivo y contador de nodos activos. + * *Bloqueado por:* Tarea 2.1.2. + * *Desbloquea:* Tarea 2.2.2. +* **Tarea 2.2.2 [FUNC-004]:** Integrar el tablero en la infraestructura web de MxOS bajo ``mirrors.mx-os.mx``. + * *Bloqueado por:* Tarea 2.2.1. + * *Desbloquea:* Hito 2.3. + +Hito 2.3: Publicación del Repositorio de Código Abierto +------------------------------------------------------- +Liberar el código del tablero para auditoría comunitaria. + +* **Tarea 2.3.1 [FUNC-004]:** Documentar las instrucciones de despliegue y publicar el repositorio bajo licencia libre en el Git de la Fundación MxOS. + * *Bloqueado por:* Tarea 2.2.2. + * *Desbloquea:* Fase 3. diff --git a/docs/project/roadmaps/fase-3-federacion-upstream.rst b/docs/project/roadmaps/fase-3-federacion-upstream.rst new file mode 100644 index 0000000..78bd504 --- /dev/null +++ b/docs/project/roadmaps/fase-3-federacion-upstream.rst @@ -0,0 +1,37 @@ +========================================= +Fase 3: Federación e Integración Upstream +========================================= + +Objetivo +======== +Consolidar el puente HTTP para registrar a MxOS formalmente ante MirrorManager de Fedora, y presentar la propuesta técnica oficial ante las listas de desarrollo de Fedora y CentOS para fomentar la adopción nativa de IPFS. + +Trazabilidad: [FUNC-005], [TECH-005] + +Hitos de la Fase +================ + +Hito 3.1: Despliegue del Puente Inverso HTTP y Validación MirrorManager +----------------------------------------------------------------------- +Habilitar la fachada web pública para clientes DNF tradicionales. + +* **Tarea 3.1.1 [TECH-005]:** Configurar el proxy inverso (Caddy/Nginx) en ``mirrors.mx-os.mx`` apuntando al gateway local de Kubo. + * *Bloqueado por:* Fase 1 (Tarea 1.2.2). + * *Desbloquea:* Tarea 3.1.2. +* **Tarea 3.1.2 [TECH-005]:** Implementar el protocolo de sondeo y verificación de sincronización requerido por MirrorManager (archivo ``report_mirror``). + * *Bloqueado por:* Tarea 3.1.1. + * *Desbloquea:* Tarea 3.1.3. +* **Tarea 3.1.3 [FUNC-005]:** Dar de alta el espejo de MxOS en la base de datos de MirrorManager de Fedora como espejo oficial para México. + * *Bloqueado por:* Tarea 3.1.2. + * *Desbloquea:* Hito 3.2. + +Hito 3.2: Propuesta Técnica Upstream (RFC) +------------------------------------------ +Presentar la arquitectura a los equipos de infraestructura de Fedora y CentOS. + +* **Tarea 3.2.1 [FUNC-005]:** Redactar el documento de propuesta (RFC) detallando los beneficios de ahorro de transferencia para upstream, mitigación de caídas y modelo de distribución comunitaria. + * *Bloqueado por:* Tarea 3.1.3 y Fase 2 (Tarea 2.2.2). + * *Desbloquea:* Tarea 3.2.2. +* **Tarea 3.2.2 [FUNC-005]:** Publicar la propuesta en los foros de discusión de Fedora (categoría Infrastructure) y en la lista de correo ``centos-devel`` para abrir el diálogo sobre soporte nativo en DNF. + * *Bloqueado por:* Tarea 3.2.1. + * *Desbloquea:* Proyecto completado. diff --git a/docs/technical/spec.rst b/docs/technical/spec.rst new file mode 100644 index 0000000..48c1cf8 --- /dev/null +++ b/docs/technical/spec.rst @@ -0,0 +1,27 @@ +====================== +Especificación Técnica +====================== + +Visión General +============== +Este documento consolida la arquitectura de ingeniería del sistema de distribución de espejos de MxOS. Describe cómo interactúan el demonio Kubo de IPFS, el subsistema de resolución DNSLink, la capa de ingesta automatizada y el puente HTTP para MirrorManager. + +Mapeo de Requisitos Técnicos +============================ + +* **[TECH-001] Ingesta Upstream y Empaquetado UnixFS:** Cumple con `[FUNC-001]`. Sincroniza directorios remotos y genera la estructura de bloques direccionada por contenido. +* **[TECH-002] Direccionamiento de Subnodos DAG:** Cumple con `[FUNC-002]`. Permite la extracción y pineo recursivo de CIDs secundarios en ramas del árbol de archivos. +* **[TECH-003] Topología DNSLink y Delegación:** Cumple con `[FUNC-003]`. Implementa el registro TXT canónico en la zona DNS de MxOS para el enrutamiento inmutable. +* **[TECH-004] Descubridor de Proveedores DHT:** Cumple con `[FUNC-004]`. Ejecuta sondeos de red hacia la DHT para compilar métricas de nodos proveedores sin telemetría. +* **[TECH-005] Puente Inverso HTTP y MirrorManager:** Cumple con `[FUNC-005]`. Conecta peticiones DNF estándar con el gateway local de Kubo y expone el punto de entrada oficial para el proyecto Fedora. + +Documentos del Dominio +====================== + +.. toctree:: + :maxdepth: 1 + + specs/arquitectura-distribucion + specs/resolucion-dnslink + specs/puente-mirrormanager + specs/ingesta-repositorios diff --git a/docs/technical/specs/arquitectura-distribucion.rst b/docs/technical/specs/arquitectura-distribucion.rst new file mode 100644 index 0000000..77fe488 --- /dev/null +++ b/docs/technical/specs/arquitectura-distribucion.rst @@ -0,0 +1,58 @@ +======================================= +Arquitectura de Distribución sobre IPFS +======================================= + +Identificadores Técnicos: [TECH-001], [TECH-002] + +Diagrama de Flujo del Sistema +============================= + +.. code-block:: text + + +------------------------+ +---------------------------+ + | Upstream RHEL / Fedora | ---> | Nodo Servidor MxOS | + +------------------------+ +---------------------------+ + | + v + +---------------------------+ + | Generación de UnixFS DAG | + | (ipfs add / filestore) | + +---------------------------+ + | + v + +---------------------------+ + | Actualización DNSLink | + | _dnslink.mirrors.mx-os.mx | + +---------------------------+ + | + +-------------------------+-------------------------+ + | | + v v + +-----------------------------+ +-----------------------------+ + | Colaborador Nivel 1 (ISOs) | <== Bitswap P2P ==> | Colaborador Nivel 2 (BaseOS)| + | ipfs pin add /.../fedora/iso| | ipfs pin add /.../BaseOS | + +-----------------------------+ +-----------------------------+ + | | + v v + +-----------------------------+ +-----------------------------+ + | Gateway local (puerto 8080) | | Gateway local (puerto 8080) | + +-----------------------------+ +-----------------------------+ + | | + v v + +-----------------------------+ +-----------------------------+ + | Cliente DNF (localhost) | | Cliente DNF (localhost) | + +-----------------------------+ +-----------------------------+ + +Componentes Principales +======================= + +Demonio Kubo +------------ +* **Implementación:** Kubo (Go-IPFS) versión empaquetada para Fedora/CentOS en Copr (``renich/kubo``). +* **Almacén de bloques:** Base de datos badgerds o flatfs para alto rendimiento en lecturas aleatorias. +* **Protocolos de transporte:** TCP y QUIC habilitados en el puerto 4001 para transversalidad óptima de NAT y firewalls residenciales. +* **Gateway local:** Escucha en ``127.0.0.1:8080`` permitiendo acceso HTTP sin exponer la interfaz de control RPC (puerto 5001). + +Direccionamiento UnixFS DAG +--------------------------- +Cada repositorio se procesa como un grafo acíclico dirigido (DAG) de UnixFS v1/v2. Los archivos grandes (imágenes ISO) se fragmentan en bloques de 1 MB con funciones hash SHA-256 o BLAKE3, garantizando que si dos versiones comparten paquetes o bloques de datos idénticos, estos se dedupliquen automáticamente en el almacén global. diff --git a/docs/technical/specs/ingesta-repositorios.rst b/docs/technical/specs/ingesta-repositorios.rst new file mode 100644 index 0000000..59b3e55 --- /dev/null +++ b/docs/technical/specs/ingesta-repositorios.rst @@ -0,0 +1,31 @@ +==================================== +Ingesta de Repositorios y Telemetría +==================================== + +Identificadores Técnicos: [TECH-001], [TECH-004] + +Flujo de Ingesta Upstream +========================= +El ciclo de actualización del nodo central de MxOS se ejecuta de manera automatizada mediante temporizadores de systemd y comprende cuatro etapas: + +1. **Sincronización diferencial con rsync:** Se obtienen los paquetes y metadatos actualizados desde los espejos de nivel 1 (Tier-1) de Fedora y CentOS Stream hacia un directorio de preparación (staging) local. +2. **Generación del grafo UnixFS (Filestore):** Para evitar la duplicación de cientos de gigabytes en el disco del servidor, se utiliza la función ``--nocopy`` de Kubo con el subsistema filestore habilitado: + + .. code-block:: bash + + ipfs add -r --nocopy --cid-version=1 --hash=sha2-256 /srv/mirrors/staging/ +3. **Actualización de Registros DNSLink:** El CID raíz resultante de la ingesta se publica automáticamente en el servidor de nombres de MxOS mediante actualización dinámica de DNS (RFC 2136 / nsupdate) o vía la API de gestión de zona. +4. **Anuncio en el enjambre:** El nodo central anuncia la provisión de los nuevos CIDs a la DHT de IPFS. + +Descubrimiento de Nodos y Telemetría Pasiva +=========================================== +Para alimentar el tablero público en ``mirrors.mx-os.mx`` sin violar la privacidad de los colaboradores, el servicio recolector opera de la siguiente forma: + +1. **Consulta a la DHT:** Se invoca periódicamente la interfaz RPC de Kubo o la instrucción de línea de comandos para consultar proveedores del CID raíz activo: + + .. code-block:: bash + + ipfs dht findprovs -n 0 +2. **Extracción de multiaddrs:** El comando retorna los identificadores de par (PeerID) y las direcciones de red asociadas (IPv4/IPv6 y puertos de escucha). +3. **Geolocalización aproximada en memoria:** Las direcciones IP públicas se contrastan contra una base de datos local MaxMind GeoLite2 para extraer únicamente el país y estado o región. +4. **Almacenamiento temporal:** Los datos agregados (número de pares, concentración geográfica y latencia de respuesta) se consolidan en una base de datos SQLite/libSQL o en memoria para ser consumidos por la interfaz web reactiva. diff --git a/docs/technical/specs/puente-mirrormanager.rst b/docs/technical/specs/puente-mirrormanager.rst new file mode 100644 index 0000000..a5502a3 --- /dev/null +++ b/docs/technical/specs/puente-mirrormanager.rst @@ -0,0 +1,68 @@ +================================== +Puente HTTP y Fedora MirrorManager +================================== + +Identificador Técnico: [TECH-005] + +Integración con MirrorManager +============================= +Fedora gestiona su infraestructura de distribución global mediante MirrorManager (`mirrormanager2`). Para registrar formalmente a MxOS como el primer espejo oficial en México, se requiere: + +1. Exposición de puntos finales HTTP y HTTPS estables y de alta velocidad. +2. Soporte para el protocolo de verificación de sincronización (archivo ``report_mirror``). +3. Respuesta rápida en peticiones GET y HEAD para metadatos de repositorio. + +Topología del Puente Inverso +============================ +En el servidor cabecera de MxOS (ejemplo: ``mirrors.mx-os.mx``), un servidor web de alto rendimiento (Caddy o Nginx) actúa como terminador TLS y proxy inverso directo hacia el gateway HTTP de Kubo: + +.. code-block:: text + + Petición DNF Upstream (Internet) + | + v + +---------------------------------------+ + | Caddy / Nginx (mirrors.mx-os.mx:443) | + | Certificados Let's Encrypt / TLS 1.3 | + +---------------------------------------+ + | + | proxy_pass http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/ + v + +---------------------------------------+ + | Gateway HTTP de Kubo (IPFS Local) | + +---------------------------------------+ + | + v + +---------------------------------------+ + | Enjambre P2P de Nodos Guardianes | + +---------------------------------------+ + +Configuración de Ejemplo para Caddy +=================================== +El servidor web delega la entrega de archivos estáticos al gateway local de IPFS: + +.. code-block:: text + + mirrors.mx-os.mx { + encode zstd gzip + + # Proxy transparente hacia el gateway de IPFS + reverse_proxy http://127.0.0.1:8080 { + rewrite /ipns/mirrors.mx-os.mx{path} + header_up Host {upstream_hostport} + } + + log { + output stdout + format filter { + wrap json + fields { + common_log delete + } + } + } + } + +Beneficio Operativo +=================== +Este desacoplamiento permite que los clientes externos utilicen el espejo como si fuera un servidor web convencional, mientras que por debajo, el servidor cabecera obtiene los bloques faltantes desde la red comunitaria de nodos guardianes, reduciendo drásticamente la carga de salida del nodo central. diff --git a/docs/technical/specs/resolucion-dnslink.rst b/docs/technical/specs/resolucion-dnslink.rst new file mode 100644 index 0000000..398fdea --- /dev/null +++ b/docs/technical/specs/resolucion-dnslink.rst @@ -0,0 +1,32 @@ +================================ +Resolución Inmutable con DNSLink +================================ + +Identificador Técnico: [TECH-003] + +Fundamento +========== +El direccionamiento directo por CID (ejemplo: ``/ipfs/bafy...``) es inmutable; cualquier cambio en un paquete genera un nuevo CID raíz. Por su parte, el Sistema de Nombres Interplanetario tradicional (IPNS) basado en DHT experimenta una latencia de resolución prohibitiva para las consultas rápidas de metadatos de DNF. + +Para solventar esta limitación, el proyecto utiliza **DNSLink**. DNSLink asocia un registro TXT en el sistema de nombres de dominio convencional con el CID raíz activo de IPFS. + +Topología de Registros DNS +========================== +En los servidores de nombres autoritativos para el dominio ``mx-os.mx``, se definen los siguientes registros: + +.. code-block:: zone + + ; Registro raíz del portal de espejos + _dnslink.mirrors.mx-os.mx. 300 IN TXT "dnslink=/ipfs/bafyrei..." + + ; Subdominios dedicados opcionales para granularidad independiente + _dnslink.fedora.mirrors.mx-os.mx. 300 IN TXT "dnslink=/ipfs/bafyfed..." + _dnslink.centos.mirrors.mx-os.mx. 300 IN TXT "dnslink=/ipfs/bafycen..." + +Mecánica de Resolución en Kubo +============================== +1. Un cliente solicita un recurso bajo la ruta ``/ipns/mirrors.mx-os.mx/fedora/iso``. +2. Kubo extrae el nombre de dominio y consulta el registro TXT de ``_dnslink.mirrors.mx-os.mx`` utilizando DNS sobre HTTPS (DoH) o los resolutores del sistema local. +3. El registro TXT devuelve el prefijo ``dnslink=/ipfs/``. +4. Kubo reemplaza internamente la ruta por ``/ipfs//fedora/iso`` y procede a recuperar los bloques vía Bitswap o desde la caché local. +5. El tiempo de vida (TTL) del registro se fija en 300 segundos (5 minutos) para permitir propagación rápida tras cada ciclo de sincronización. diff --git a/etc/caddy/Caddyfile b/etc/caddy/Caddyfile new file mode 100644 index 0000000..f976b65 --- /dev/null +++ b/etc/caddy/Caddyfile @@ -0,0 +1,25 @@ +# Configuración Caddy para mirrors.mx-os.mx +mirrors.mx-os.mx { + encode zstd gzip + + # Proxy transparente hacia el gateway local de Kubo + reverse_proxy http://127.0.0.1:8080 { + rewrite /ipns/mirrors.mx-os.mx{path} + header_up Host {upstream_hostport} + transport http { + read_buffer 0 + } + } + + header { + Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" + X-Content-Type-Options "nosniff" + X-Frame-Options "SAMEORIGIN" + Referrer-Policy "strict-origin-when-cross-origin" + } + + log { + output stdout + format json + } +} diff --git a/etc/mirrors.env b/etc/mirrors.env new file mode 100644 index 0000000..9f5af41 --- /dev/null +++ b/etc/mirrors.env @@ -0,0 +1,19 @@ +# Configuración de la Red de Espejos MxOS sobre IPFS + +# Directorios de preparación y datos locales +MIRRORS_STAGING_DIR="${MIRRORS_STAGING_DIR:-$HOME/.local/share/mxos-mirrors/staging}" +MIRRORS_LOG_DIR="${MIRRORS_LOG_DIR:-$HOME/.local/share/mxos-mirrors/logs}" + +# Configuración de IPFS +IPFS_PATH="${IPFS_PATH:-$HOME/.ipfs}" +IPFS_API_URL="${IPFS_API_URL:-/ip4/127.0.0.1/tcp/5001}" +IPFS_USE_NOCOPY="${IPFS_USE_NOCOPY:-false}" + +# Dominios y DNSLink +CF_ZONE_ID="2bd35b00a854bc77cfd38009f977ea3c" +MIRRORS_DOMAIN="mirrors.mx-os.mx" +MIRRORS_DNSLINK_RECORD="_dnslink.mirrors.mx-os.mx" + +# Espejos Upstream +FEDORA_UPSTREAM_RSYNC="rsync://dl.fedoraproject.org/pub/fedora/linux" +CENTOS_UPSTREAM_RSYNC="rsync://mirror.stream.centos.org/centos-stream" diff --git a/etc/nginx/mirrors.mx-os.mx.conf b/etc/nginx/mirrors.mx-os.mx.conf new file mode 100644 index 0000000..30fd53d --- /dev/null +++ b/etc/nginx/mirrors.mx-os.mx.conf @@ -0,0 +1,43 @@ +# Configuración Nginx para mirrors.mx-os.mx como terminador TLS y proxy hacia Kubo +server { + listen 80; + listen [::]:80; + server_name mirrors.mx-os.mx; + + # Redirección forzada hacia HTTPS + return 301 https://$host$request_uri; +} + +server { + http2 on; + listen 443 ssl; + listen [::]:443 ssl; + server_name mirrors.mx-os.mx; + + # Certificados SSL Let's Encrypt + ssl_certificate /etc/letsencrypt/live/mirrors.mx-os.mx/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/mirrors.mx-os.mx/privkey.pem; + + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + # Encabezados de seguridad + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Proxy inverso transparente hacia el gateway de Kubo + location / { + proxy_pass http://127.0.0.1:8080/ipns/mirrors.mx-os.mx/; + proxy_set_header Host 127.0.0.1:8080; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Deshabilitar buffering para flujo ágil de paquetes y artefactos de gran tamaño + proxy_buffering off; + proxy_read_timeout 300s; + proxy_connect_timeout 10s; + } +} diff --git a/systemd/mxos-mirror.service b/systemd/mxos-mirror.service new file mode 100644 index 0000000..d64f617 --- /dev/null +++ b/systemd/mxos-mirror.service @@ -0,0 +1,15 @@ +[Unit] +Description=Sincronización y publicación de la Red de Espejos MxOS sobre IPFS +Documentation=https://mirrors.mx-os.mx/README.rst +After=network-online.target ipfs.service +Wants=network-online.target + +[Service] +Type=oneshot +WorkingDirectory=%h/Projects/mxos/mirrors +ExecStart=%h/Projects/mxos/mirrors/bin/mxos-mirror.bash run-all +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=default.target diff --git a/systemd/mxos-mirror.timer b/systemd/mxos-mirror.timer new file mode 100644 index 0000000..3b8661b --- /dev/null +++ b/systemd/mxos-mirror.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Temporizador de sincronización periódica de espejos MxOS +Documentation=https://mirrors.mx-os.mx/README.rst + +[Timer] +OnCalendar=*-*-* 04:00:00 +RandomizedDelaySec=1800 +Persistent=true + +[Install] +WantedBy=timers.target