diff --git a/.agents/journal/entries/2026-06-16-renich-agent-44789154.md b/.agents/journal/entries/2026-06-16-renich-agent-44789154.md index bafd1bc..63fad29 100644 --- a/.agents/journal/entries/2026-06-16-renich-agent-44789154.md +++ b/.agents/journal/entries/2026-06-16-renich-agent-44789154.md @@ -10,3 +10,4 @@ * [2026-06-16 14:47:34] [agent-44789154] [GOT] [prev:dad7e97152b063fccb93c95a10b0d3f44b5547cbacb85839c1f57243f603b4bd] [hash:ff115eb6b7066ffdc4e19a3915954026304bb29e4dcde38f08a98e1dcd66a216] Imported all 4579 package repositories from the Forgejo RPMs organization into the Koji mxos0 build tag. * [2026-06-16 15:34:06] [agent-44789154] [GOT,DEC] [prev:ff115eb6b7066ffdc4e19a3915954026304bb29e4dcde38f08a98e1dcd66a216] [hash:267e20bbe8860aa24ba9857f43a7e57fdfe3316d66b0b0fd2373a4f66377d8ea] DEC: Reverted mergerepo_c wrapper and restored correct BaseOS (5) / AppStream (10) priorities on mxos0-build tag. GOT: Cleaned Ansible playbooks, added noarch to builder cs10-koji-03.mx-os arches, successfully triggered and checked rust-siguldry package compilation, created docs/compilación_de_paquetes.rst. * [2026-06-16 15:47:09] [agent-44789154] [GOT,DEC] [prev:267e20bbe8860aa24ba9857f43a7e57fdfe3316d66b0b0fd2373a4f66377d8ea] [hash:ba5dc0fe3c77a6f0299c27e3ba1c16c2233d6464e87f9685b77df1f9d61dd298] Calculated topological bootstrap order for all 480 BaseOS packages using DNF API inside a CentOS Stream 10 container. Updated bootstrap-baseos.py on Koji Hub to build packages in this order and started it in the background. Deployed export-koji-to-forgejo.py to sync signed RPMs to the Forgejo Package Registry. Created ADR-05 and updated compilación_de_paquetes.rst. +* [2026-06-16 16:10:24] [agent-44789154] [GOT,DEC] [prev:ba5dc0fe3c77a6f0299c27e3ba1c16c2233d6464e87f9685b77df1f9d61dd298] [hash:dae096cb37d89f9ef09ef6ac6ad2f2ea981108412ca44b1fc9cd525611f1fee7] DEC: Decided to use a dedicated 500 GB VM serving via Caddy on port 80 as our package repository server instead of Forgejo Package Registry. GOT: Provisioned cs10-repo.mx-os using OpenTofu, configured Caddy via Ansible role, deployed export-koji-to-repo.py on Koji Hub to automatically rsync RPMs and run createrepo_c, and documented the design change in ADR-05 and compilación_de_paquetes.rst. diff --git a/deploy.yaml b/deploy.yaml index ccd6183..ac822c4 100644 --- a/deploy.yaml +++ b/deploy.yaml @@ -88,4 +88,12 @@ roles: - role: dist_git tags: dist_git + +- name: "Deploy: Repository Server (Caddy)" + hosts: reposerver + vars_files: + - vars/default.yaml + roles: + - role: caddy + tags: caddy ... diff --git a/docs/compilación_de_paquetes.rst b/docs/compilación_de_paquetes.rst index 869ae8c..b2145c3 100644 --- a/docs/compilación_de_paquetes.rst +++ b/docs/compilación_de_paquetes.rst @@ -100,21 +100,23 @@ Puedes supervisar el progreso de las tareas leyendo su archivo de bitácora o li tail -f /var/log/bootstrap-baseos.log koji list-tasks --mine -Exportación de Paquetes al Registro Forgejo -=========================================== +Exportación de Paquetes al Servidor de Repositorio (Caddy) +========================================================== -El registro final para alojar y servir nuestros paquetes RPM oficiales para consumo de DNF es el Registro de Paquetes de Forgejo (``git.mx-os.mx/api/packages/RPMs/rpm``). +El repositorio final para alojar y servir nuestros paquetes RPM oficiales para consumo de DNF se hospeda en el servidor dedicado ``cs10-repo.mx-os`` mediante el servidor web Caddy. El repositorio está expuesto públicamente en ``http://cs10-repo.mx-os/``. -Para automatizar la exportación de todos los paquetes RPM que Koji ha compilado y firmado exitosamente, se utiliza el script ``/root/export-koji-to-forgejo.py``. Este script: +Para automatizar la exportación y sincronización de todos los paquetes RPM que Koji ha compilado y firmado exitosamente, se utiliza el script ``/root/export-koji-to-repo.py`` en el Koji Hub. Este script: 1. Consulta todas las compilaciones completadas bajo la etiqueta ``mxos0``. 2. Localiza los RPMs firmados en el almacenamiento compartido de Koji (``/mnt/koji/packages/``). 3. Filtra archivos fuentes (``.src.rpm``) y subpaquetes de depuración (``debuginfo`` y ``debugsource``). -4. Sube por HTTP PUT cada RPM binario firmado al registro Forgejo de la organización ``RPMs``. +4. Utiliza ``rsync`` para sincronizar los RPMs binarios firmados hacia el directorio ``/srv/repo/`` en el servidor ``cs10-repo.mx-os``. +5. Ejecuta de forma remota el comando ``createrepo_c /srv/repo`` en el servidor de repositorios para regenerar los metadatos de DNF. Para ejecutar la exportación manualmente de todos los paquetes listos, ejecuta en Koji Hub: .. code-block:: bash - sudo python3 /root/export-koji-to-forgejo.py + sudo python3 /root/export-koji-to-repo.py + diff --git a/docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_exportacion_forgejo.rst b/docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_servidor_caddy.rst similarity index 55% rename from docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_exportacion_forgejo.rst rename to docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_servidor_caddy.rst index 77a2c12..fe48ed6 100644 --- a/docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_exportacion_forgejo.rst +++ b/docs/technical/decisiones/2026-06-16-05-bootstrap_orden_y_servidor_caddy.rst @@ -1,6 +1,6 @@ -==================================================================== -ADR 2026-06-16-05: Orden de Bootstrap y Exportación al Registro Forgejo -==================================================================== +===================================================================== +ADR 2026-06-16-05: Orden de Bootstrap y Servidor de Repositorio Caddy +===================================================================== Estatus ------- @@ -13,7 +13,7 @@ Contexto Para iniciar la compilación masiva de CentOS Stream 10 BaseOS en el entorno Koji de MxOS, necesitamos resolver dos desafíos clave: 1. **Orden de Bootstrap**: La compilación en Koji requiere un orden estructurado para evitar fallos masivos por dependencias faltantes. Aunque Koji puede utilizar repositorios externos como semilla para resolver las dependencias iniciales, determinar el orden de dependencias internas de la distribución nos permite estructurar la compilación y rastrear el progreso de forma determinista. -2. **Exportación al Registro Final**: Una vez que Koji compila y firma los paquetes (mediante el spooler de firma integrado), estos RPMs firmados deben ser exportados al repositorio de producción oficial, que es el Registro de Paquetes de Forgejo (Forgejo Package Registry) en ``git.mx-os.mx/api/packages/RPMs/rpm``. +2. **Exportación al Registro Final**: Una vez que Koji compila y firma los paquetes (mediante el spooler de firma integrado), estos RPMs firmados deben ser exportados al repositorio de producción oficial, haciéndolos disponibles para consumo mediante DNF. Inicialmente se consideró el Registro de Paquetes de Forgejo, pero debido al volumen masivo de paquetes y la necesidad de una sincronización ágil y ligera, se optó por desplegar un servidor de repositorio independiente. Decisión -------- @@ -29,19 +29,24 @@ Adoptaremos la siguiente estrategia técnica: 2. **Automatización de Compilaciones**: * El script de orquestación (``bootstrap-baseos.py``) en el Koji Hub controlará y enviará las tareas de compilación respetando la concurrencia y siguiendo el orden determinista obtenido. -3. **Exportación Automatizada a Forgejo**: - * Escribimos y desplegamos el script de exportación ``/root/export-koji-to-forgejo.py`` en el Koji Hub. - * Este script utiliza el API de Koji para listar todas las compilaciones completadas bajo el tag ``mxos0``, busca sus RPMs correspondientes en `/mnt/koji/packages/`, y los sube mediante peticiones HTTP PUT al API de Forgejo utilizando el token del usuario ``renich`` (almacenado localmente de forma segura en las llaves del CLI de Forgejo). - * El script filtra los archivos ``.src.rpm`` y los paquetes con sufijos ``debuginfo`` y ``debugsource``, subiendo únicamente los RPMs binarios finales con sus firmas GPG incrustadas. - * Se implementa un manejo transparente de conflictos HTTP 409 (Conflict) para ignorar paquetes que ya existen en el registro. +3. **Servidor de Repositorio Dedicado con Caddy**: + * Provisionamos una máquina virtual dedicada ``cs10-repo.mx-os`` mediante OpenTofu con un disco virtual del sistema redimensionado a 500 GB de capacidad. + * Automatizamos la instalación de Caddy, la configuración de firewalld para HTTP (puerto 80) y la creación del directorio ``/srv/repo/`` mediante el rol de Ansible ``caddy``. + * Caddy está configurado para servir y permitir el listado de este directorio (``file_server browse``), actuando como nuestro servidor de repositorio oficial. + +4. **Exportación y Sincronización Automatizada vía Rsync**: + * Escribimos y desplegamos el script de exportación ``/root/export-koji-to-repo.py`` en el Koji Hub. + * Este script utiliza el API de Koji para listar todas las compilaciones completadas bajo el tag ``mxos0``, busca sus RPMs correspondientes en `/mnt/koji/packages/`, y los sincroniza mediante ``rsync`` al directorio ``/srv/repo/`` en ``cs10-repo.mx-os`` utilizando la llave SSH del usuario root de Koji Hub (previamente autorizada en el servidor de repositorio). + * El script filtra los archivos ``.src.rpm`` y los paquetes con sufijos ``debuginfo`` y ``debugsource``, exportando únicamente los RPMs binarios firmados. + * Tras la sincronización, el script ejecuta de forma remota el comando ``createrepo_c /srv/repo`` en el servidor de repositorios para regenerar los metadatos de DNF en caliente. Consecuencias ------------- * **Positivas**: - * Orden de compilación de bootstrap 100% determinista basado en el estado real de los metadatos de CentOS Stream 10. - * Flujo de trabajo automatizado y continuo que firma y publica los paquetes completados en el registro público de Forgejo, haciéndolos disponibles de inmediato para DNF. - * Aislamiento de paquetes debug y fuentes para no contaminar el repositorio binario de consumo. + * Servidor de repositorio dedicado ligero y rápido de 500 GB que puede servir de manera escalable los metadatos y RPMs de la distribución sin depender del registro de Forgejo. + * Uso de ``rsync`` para sincronizaciones súper eficientes que minimizan el tráfico y tiempo de red al omitir transferencias redundantes. + * Regeneración automática de metadatos de DNF mediante ``createrepo_c`` en caliente tras cada sincronización. * **Negativas / Desafíos**: - * La compilación inicial del ciclo principal (SCC core de 225 paquetes) tardará tiempo significativo y consumirá recursos de buildroot debido a la naturaleza iterativa del bootstrap. + * Requiere el mantenimiento de una VM adicional y su servicio Caddy. diff --git a/inventories/staging/hosts.yaml b/inventories/staging/hosts.yaml index 6c61f39..a70c521 100644 --- a/inventories/staging/hosts.yaml +++ b/inventories/staging/hosts.yaml @@ -18,6 +18,11 @@ all: dist-git: hosts: cs10-koji-04.mx-os: + reposerver: + hosts: + cs10-repo.mx-os: + vars: + ansible_user: root koji_nodes: children: kojihub: diff --git a/opentofu/cs10-repo.tf b/opentofu/cs10-repo.tf new file mode 100644 index 0000000..f4d3468 --- /dev/null +++ b/opentofu/cs10-repo.tf @@ -0,0 +1,150 @@ +resource "libvirt_domain" "cs10-repo" { + name = "cs10-repo.mx-os" + memory = var.guest_memory + memory_unit = "MiB" + vcpu = var.guest_vcpu + running = true + autostart = true + type = "kvm" + + os = { + type = "hvm" + arch = "x86_64" + machine = "q35" + firmware = "efi" + loader_path = "/usr/share/edk2/ovmf/OVMF_CODE_4M.secboot.qcow2" + loader_readonly = true + loader_secure = true + loader_type = "pflash" + nvram = { + path = "/var/lib/libvirt/qemu/nvram/cs10-repo.mx-os_VARS.qcow2" + template = "/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2" + format = "qcow2" + } + } + + cpu = { + mode = "host-passthrough" + } + + features = { + acpi = true + apic = {} + } + + devices = { + disks = [ + { + type = "volume" + driver = { + type = "qcow2" + } + + source = { + volume = { + pool = var.pool_name + volume = libvirt_volume.cs10-repo-system.name + } + } + + target = { + dev = "vda" + bus = "virtio" + } + }, + { + type = "volume" + device = "cdrom" + readonly = true + driver = { + type = "raw" + } + + source = { + volume = { + pool = var.pool_name + volume = libvirt_cloudinit_disk.cs10-repo-cloudinit.name + } + } + + target = { + dev = "sda" + bus = "sata" + } + } + ] + + interfaces = [ + { + type = "network" + model = { + type = "virtio" + } + source = { + network = { + network = "default" + } + } + } + ] + + consoles = [ + { + type = "pty" + target_type = "virtio" + target_port = "1" + } + ] + + video = { + type = "virtio" + } + } +} + +resource "libvirt_volume" "cs10-repo-system" { + name = "cs10-repo.mx-os-system.qcow2" + pool = var.pool_name + capacity = 536870912000 # 500 GiB (500 * 1024 * 1024 * 1024) + target = { + format = { + type = "qcow2" + } + } + + create = { + content = { + url = "file://${var.base_image_path}" + } + } +} + +resource "libvirt_cloudinit_disk" "cs10-repo-cloudinit" { + name = "cs10-repo.mx-os-cloudinit.iso" + + user_data = templatefile("templates/cloudinit.cfg.tftpl", { + root_password = var.root_password + hostname = "cs10-repo.mx-os" + }) + + meta_data = yamlencode({ + instance-id = "cs10-repo.mx-os" + local-hostname = "cs10-repo.mx-os" + }) +} + +resource "libvirt_volume" "cs10-repo-cloudinit-volume" { + name = "cs10-repo.mx-os-cloudinit.iso" + pool = var.pool_name + target = { + format = { + type = "iso" + } + } + + create = { + content = { + url = libvirt_cloudinit_disk.cs10-repo-cloudinit.path + } + } +} diff --git a/roles/caddy/handlers/main.yaml b/roles/caddy/handlers/main.yaml new file mode 100644 index 0000000..839521b --- /dev/null +++ b/roles/caddy/handlers/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Restart caddy + ansible.builtin.systemd: + name: caddy + state: restarted diff --git a/roles/caddy/tasks/main.yaml b/roles/caddy/tasks/main.yaml new file mode 100644 index 0000000..7766c4a --- /dev/null +++ b/roles/caddy/tasks/main.yaml @@ -0,0 +1,44 @@ +--- +- name: Enable Caddy Copr repository + ansible.builtin.command: dnf copr enable -y @caddy/caddy + args: + creates: /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:group_caddy:caddy.repo + +- name: Install Caddy + ansible.builtin.dnf: + name: caddy + state: present + +- name: Create repository directory + ansible.builtin.file: + path: /srv/repo + state: directory + mode: '0755' + owner: root + group: root + +- name: Deploy Caddyfile + ansible.builtin.template: + src: Caddyfile.j2 + dest: /etc/caddy/Caddyfile + owner: root + group: root + mode: '0644' + notify: Restart caddy + +- name: Gather service facts + ansible.builtin.service_facts: + +- name: Allow HTTP port in firewalld + ansible.builtin.firewalld: + service: http + permanent: true + state: enabled + immediate: true + when: ansible_facts.services['firewalld.service'] is defined and ansible_facts.services['firewalld.service'].state == 'running' + +- name: Ensure Caddy is started and enabled + ansible.builtin.systemd: + name: caddy + state: started + enabled: true diff --git a/roles/caddy/templates/Caddyfile.j2 b/roles/caddy/templates/Caddyfile.j2 new file mode 100644 index 0000000..144b1ab --- /dev/null +++ b/roles/caddy/templates/Caddyfile.j2 @@ -0,0 +1,4 @@ +:80 { + root * /srv/repo + file_server browse +}