From 23c556938bfcd90da9f65498c4a59c11d0a65ebe Mon Sep 17 00:00:00 2001 From: Xavor Date: Thu, 4 Sep 2025 00:39:48 +0200 Subject: [PATCH] =?UTF-8?q?a=C3=B1adido=20script=20clientes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- repo/configmap/repo-sources.yaml | 54 ++++++++++-- repo/configure-local-repos.sh | 144 +++++++++++++++++++++++++++++++ repo/readme.md | 75 +++++++++------- 3 files changed, 239 insertions(+), 34 deletions(-) create mode 100644 repo/configure-local-repos.sh diff --git a/repo/configmap/repo-sources.yaml b/repo/configmap/repo-sources.yaml index e682dc6..03053b3 100644 --- a/repo/configmap/repo-sources.yaml +++ b/repo/configmap/repo-sources.yaml @@ -4,28 +4,55 @@ metadata: name: repo-sources namespace: repo data: + # Lista de orígenes a espejar + # Formato por línea: NAME|URL|SUBDIR + # SUBDIR cuelga de /mirror/repos (asegúrate de que tu Deployment monta el PVC en /usr/local/apache2/htdocs con subPath repos) sources.txt: | + # openSUSE Leap 15.6 (básicos + updates) repo-oss|http://download.opensuse.org/distribution/leap/15.6/repo/oss/|opensuse/leap/15.6/oss repo-non-oss|http://download.opensuse.org/distribution/leap/15.6/repo/non-oss/|opensuse/leap/15.6/non-oss update-oss|http://download.opensuse.org/update/leap/15.6/oss/|opensuse/leap/15.6/update/oss update-non-oss|http://download.opensuse.org/update/leap/15.6/non-oss/|opensuse/leap/15.6/update/non-oss update-sle|http://download.opensuse.org/update/leap/15.6/sle/|opensuse/leap/15.6/update/sle backports|http://download.opensuse.org/update/leap/15.6/backports/|opensuse/leap/15.6/update/backports + + # Codecs openh264 openh264|http://codecs.opensuse.org/openh264/openSUSE_Leap/|opensuse/openh264 + + # Terceros (opcional) nvidia|https://download.nvidia.com/opensuse/leap/15.6/|thirdparty/nvidia/leap/15.6 k8s-stable|https://pkgs.k8s.io/core:/stable:/v1.33/rpm/|thirdparty/kubernetes/core/stable/v1.33/rpm + # Claves públicas a publicar en /mirror/keys + # Formato por línea: NAME|URL|FILENAME + # Ajusta las URLs si prefieres otras fuentes/ubicaciones oficiales + keys.txt: | + opensuse|https://download.opensuse.org/repositories/openSUSE:/Leap:/15.6:/Update/standard/repodata/repomd.xml.key|RPM-GPG-KEY-openSUSE + nvidia|https://download.nvidia.com/opensuse/repodata/repomd.xml.key|RPM-GPG-KEY-NVIDIA + k8s|https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key|RPM-GPG-KEY-k8s + + # Script de sincronización diario (CronJob) + # - Sincroniza repos a /mirror/repos/... + # - Publica claves GPG en /mirror/keys sync.sh: | + #!/usr/bin/env bash set -euo pipefail SRC_LIST="/config/sources.txt" + KEYS_LIST="/config/keys.txt" + DEST_ROOT="/mirror/repos" + DEST_KEYS="/mirror/keys" - mkdir -p "$DEST_ROOT" + mkdir -p "$DEST_ROOT" "$DEST_KEYS" - command -v rsync >/dev/null 2>&1 || echo "Aviso: rsync no disponible; usaré wget para HTTP/HTTPS" + # Requisitos command -v wget >/dev/null 2>&1 || { echo "ERROR: wget requerido"; exit 1; } + if ! command -v rsync >/dev/null 2>&1; then + echo "Aviso: rsync no disponible; usaré wget para HTTP/HTTPS" + fi + echo "===== SYNC REPOS =====" while IFS='|' read -r NAME URL SUBDIR; do [[ -z "${NAME:-}" || "${NAME:0:1}" == "#" ]] && continue @@ -35,22 +62,39 @@ data: echo "==> Sync ${NAME} (${URL}) -> ${DEST}" if [[ "$URL" == rsync://* ]]; then + # Sincronización eficiente por rsync (si el mirror lo soporta) rsync -aH --delete --partial --info=stats1,progress2 "${URL}" "${DEST}/" else + # Mirror vía HTTP/HTTPS con wget TMP="${DEST}.tmp" mkdir -p "$TMP" + # -m (mirror), -np (no subir), -nH (sin host en ruta), robots=off wget -m -np -nH -e robots=off -P "$TMP" --no-verbose --show-progress "$URL" + # Mover contenido espeljado a DEST (limpiando y dejando estructura limpia) shopt -s dotglob nullglob - SRC_CONTENT=("$TMP"/*) - if [[ ${#SRC_CONTENT[@]} -gt 0 ]]; then + if compgen -G "$TMP/*" >/dev/null; then rsync -a --delete "$TMP"/ "$DEST"/ fi rm -rf "$TMP" fi + # Permisos legibles por httpd y Samba chmod -R a+rX "$DEST" done < "$SRC_LIST" - echo "Sync completado." + echo "===== SYNC KEYS =====" + if [[ -f "$KEYS_LIST" ]]; then + while IFS='|' read -r KNAME KURL KFILE; do + [[ -z "${KNAME:-}" || "${KNAME:0:1}" == "#" ]] && continue + echo "==> Key ${KNAME} (${KURL}) -> ${DEST_KEYS}/${KFILE}" + wget -q -O "${DEST_KEYS}/${KFILE}.tmp" "$KURL" + mv "${DEST_KEYS}/${KFILE}.tmp" "${DEST_KEYS}/${KFILE}" + chmod a+r "${DEST_KEYS}/${KFILE}" + done < "$KEYS_LIST" + else + echo "No hay KEYS_LIST ($KEYS_LIST), omitido." + fi + + echo "===== DONE =====" diff --git a/repo/configure-local-repos.sh b/repo/configure-local-repos.sh new file mode 100644 index 0000000..991d46a --- /dev/null +++ b/repo/configure-local-repos.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ============================ +# Configuración (ajusta aquí) +# ============================ +BASE_URL="${BASE_URL:-http://repo.c2et.net}" # tu dominio del mirror (sin / al final) +LEAP_VER="${LEAP_VER:-15.6}" # versión de Leap +ENABLE_NVIDIA="${ENABLE_NVIDIA:-true}" # true/false +ENABLE_K8S="${ENABLE_K8S:-true}" # true/false +DISABLE_EXTERNAL="${DISABLE_EXTERNAL:-true}" # true/false (deshabilitar repos externos) + +# Rutas base del mirror interno +REPO_BASE="${BASE_URL}/opensuse/leap/${LEAP_VER}" +KEYS_BASE="${BASE_URL}/keys" + +# Directorio de repos dnf/zypp +REPOS_DIR="/etc/zypp/repos.d" + +# ============================ +# Helpers +# ============================ +need_root() { + if [[ $EUID -ne 0 ]]; then + echo "Este script debe ejecutarse como root (o con sudo)." >&2 + exit 1 + fi +} + +have_cmd() { + command -v "$1" >/dev/null 2>&1 +} + +write_repo() { + local alias="$1" name="$2" baseurl="$3" gpgkey="$4" + local path="${REPOS_DIR}/${alias}.repo" + + cat >"${path}.tmp" <&2 + return 1 + } +} + +disable_external_repos() { + echo "Deshabilitando repos externos conocidos..." + # Deshabilita TODO lo que no sea *_local que creemos, de forma segura: + # Busca todos los alias actuales y deshabilita los que no terminen en '-local' + local aliases + aliases=$(zypper --non-interactive lr -u | awk 'NR>2 {print $1,$2}' | tail -n +1 | awk '{print $2}') + for a in $aliases; do + if [[ "$a" != *-local ]]; then + # Algunos sistemas traen alias con espacios; saltamos los complicados + if [[ "$a" =~ ^[A-Za-z0-9._:-]+$ ]]; then + zypper --non-interactive mr -d "$a" || true + fi + fi + done +} + +# ============================ +# Main +# ============================ +need_root + +if ! have_cmd zypper; then + echo "No se encontró zypper. ¿Es openSUSE/SLE este sistema?" >&2 + exit 1 +fi + +echo "== Configurando repos locales desde ${BASE_URL} para Leap ${LEAP_VER} ==" + +mkdir -p "$REPOS_DIR" + +# 1) Importa claves GPG desde tu mirror +echo "Importando claves GPG desde ${KEYS_BASE} ..." +import_key "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" || true +$ENABLE_NVIDIA && import_key "${KEYS_BASE}/RPM-GPG-KEY-NVIDIA" || true +$ENABLE_K8S && import_key "${KEYS_BASE}/RPM-GPG-KEY-k8s" || true + +# 2) Repos base de openSUSE +echo "Escribiendo archivos .repo para repos locales..." +write_repo "repo-oss-local" "repo-oss-local" "${REPO_BASE}/oss" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "repo-non-oss-local" "repo-non-oss-local" "${REPO_BASE}/non-oss" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "update-oss-local" "update-oss-local" "${REPO_BASE}/update/oss" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "update-non-oss-local" "update-non-oss-local" "${REPO_BASE}/update/non-oss" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "update-sle-local" "update-sle-local" "${REPO_BASE}/update/sle" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "update-backports-local" "update-backports-local" "${REPO_BASE}/update/backports" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" +write_repo "openh264-local" "openh264-local" "${BASE_URL}/opensuse/openh264" "${KEYS_BASE}/RPM-GPG-KEY-openSUSE" + +# 3) Repos de terceros (opcional) +if $ENABLE_NVIDIA; then + write_repo "nvidia-local" "nvidia-local" \ + "${BASE_URL}/thirdparty/nvidia/leap/${LEAP_VER}" \ + "${KEYS_BASE}/RPM-GPG-KEY-NVIDIA" +fi + +if $ENABLE_K8S; then + write_repo "k8s-stable-local" "k8s-stable-local" \ + "${BASE_URL}/thirdparty/kubernetes/core/stable/v1.33/rpm" \ + "${KEYS_BASE}/RPM-GPG-KEY-k8s" +fi + +# 4) Deshabilitar repos externos si procede +if $DISABLE_EXTERNAL; then + disable_external_repos +fi + +# 5) Refrescar repos (no interactivo) +echo "Refrescando repos..." +zypper --non-interactive --gpg-auto-import-keys ref || true + +echo +echo "== Listado final de repos ==" +zypper lr -d || true + +echo +echo "Listo. Si quieres personalizar:" +echo " BASE_URL=... LEAP_VER=... ENABLE_NVIDIA=true/false ENABLE_K8S=true/false DISABLE_EXTERNAL=true/false \\" +echo " sudo -E ./$(basename "$0")" diff --git a/repo/readme.md b/repo/readme.md index 6076628..3e66797 100644 --- a/repo/readme.md +++ b/repo/readme.md @@ -1,22 +1,30 @@ -## Cómo usarlo (rápido) +# Repositorio Privado openSUSE + +Este despliegue en Kubernetes crea un **mirror interno de repositorios de openSUSE** (y de terceros opcionales, como NVIDIA o Kubernetes). Sirve para que los servidores de nuestra red se actualicen **desde dentro**, sin depender de internet. + +El sistema funciona con: + +* **Servidor HTTP/HTTPS** → los clientes SUSE acceden vía `http://repo.c2et.net/...` o `https://repo.c2et.net/...` para descargar paquetes y metadatos. +* **Servidor Samba (SMB)** → expone la misma carpeta por red. Esto nos permite que el **“diodo de datos”** copie los repos de manera unidireccional hacia la red clasificada. Así aseguramos que las máquinas en la red sensible reciben actualizaciones sin conectividad exterior. + +La carpeta de repos se actualiza automáticamente cada día mediante un **CronJob**, que sincroniza contra los repos oficiales de openSUSE y de terceros. + +--- + +## Cómo desplegarlo 1. Ajusta **dominio** en el Ingress y (si quieres) IP fija en el Service de Samba. -2. Revisa tamaño de **PVC**. -3. (Opcional) Cambia o amplía la lista en `sources.txt`. Si tienes un mirror con **rsync**, usa `rsync://...` en la URL para más eficiencia. -4. Aplica en orden: +2. Revisa tamaño de **PVC** (mínimo 300 GB recomendado). +3. (Opcional) Cambia o amplía la lista en `sources.txt` (por ejemplo, usando mirrors con `rsync://`). +4. Despliega todo de una vez con **Kustomize**: ```bash -kubectl apply -f repo/namespace.yaml -kubectl apply -f repo/pvc.yaml -kubectl apply -f repo/configmap/repo-sources.yaml -kubectl apply -f repo/deployments/repo-server.yaml -kubectl apply -f repo/services/service-http.yaml -kubectl apply -f repo/services/service-samba.yaml # o NodePort -kubectl apply -f repo/ingress/ingress-repo.yaml -kubectl apply -f repo/cronjobs/repo-sync.yaml +kubectl apply -k repo/ ``` -5. Lanza una sync inicial **ad hoc** (sin esperar al cron) creando un Job manual: +*(Si prefieres, aún puedes aplicar los manifiestos uno por uno en el orden indicado en la carpeta `repo/`.)* + +5. Para lanzar una sincronización inicial manual (sin esperar al cron): ```bash kubectl create job --from=cronjob/repo-sync repo-sync-now -n repo @@ -27,28 +35,37 @@ kubectl logs -f job/repo-sync-now -n repo ## Configuración en los clientes SUSE -En tus servidores, añade repos apuntando a tu repo interno, por ejemplo: +En los clientes no hace falta configurar repos manualmente. Basta con ejecutar el **script de cliente** incluido en este repo (`configure-local-repos.sh`). Este script: + +* Importa las claves GPG desde `http://repo.c2et.net/keys/`. +* Crea los `.repo` apuntando al mirror interno. +* Deshabilita los repos externos para que solo se usen los `-local`. + +### Uso del script en el cliente ```bash -# HTTP (recomendado) -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/oss repo-oss-local -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/non-oss repo-non-oss-local -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/update/oss update-oss-local -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/update/non-oss update-non-oss-local -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/update/sle update-sle-local -sudo zypper ar -f http://repo.c2et.net/opensuse/leap/15.6/update/backports update-backports-local -sudo zypper ar -f http://repo.c2et.net/opensuse/openh264 openh264-local - -# Terceros (si los espejas): -sudo zypper ar -f http://repo.c2et.net/thirdparty/nvidia/leap/15.6 nvidia-local -sudo zypper ar -f http://repo.c2et.net/thirdparty/kubernetes/core/stable/v1.33/rpm k8s-stable-local +chmod +x configure-local-repos.sh +sudo ./configure-local-repos.sh ``` -> Truco: deja tus repos “externos” deshabilitados (`zypper mr -d `) y activa solo los “-local”. Así fuerzan el uso del mirror interno. +Esto deja el sistema listo para trabajar solo con los repos locales. + +--- + +## Ventajas de esta arquitectura + +* **Seguridad**: los clientes nunca salen a internet, solo acceden al repo interno. +* **Control**: el mirror se actualiza de forma programada (p. ej. de madrugada). Siempre sabemos qué versiones están disponibles. +* **Simplicidad**: los clientes usan HTTP/HTTPS estándar; el Ingress se encarga del TLS si hace falta. +* **Integración con el diodo**: gracias a Samba, la carpeta puede replicarse unidireccionalmente hacia la red clasificada. +* **Verificación**: zypper siempre valida las firmas GPG de los paquetes, aunque se distribuyan por HTTP. --- ## Sugerencias y mejoras -* **Mejor rsync**: si eliges un mirror con `rsync://`, cambia las URLs de `download.opensuse.org` a ese mirror (ej. `rsync:///opensuse/distribution/leap/15.6/repo/oss/`) para acelerar y reducir ancho de banda (usa `--delete`). -* **Throttle nocturno**: añade `--bwlimit=MB` a `rsync` si tu ventana noc +* Usar **mirrors oficiales con rsync** para ahorrar ancho de banda y tiempo de sincronización. +* Añadir `--bwlimit` en el `sync.sh` si queremos limitar consumo nocturno de ancho de banda. +* Sustituir `httpd` por `nginx` si se busca mayor rendimiento en descargas masivas. +* Proteger el Ingress con autenticación si se expone fuera de la red de confianza. +* Mantener el **script de cliente** actualizado para simplificar el alta de repos en todos los servidores SUSE.