martes, 26 de mayo de 2026

Qué sucede antes de que un dato se convierta en un embedding.?

 


No soy muy bueno cocinando, de hecho, sólo lo hago como medio de sobrevivencia cuando mi esposa esta de viaje. La preparación de una sopa por parte de un Chef de verdad es un buen ejemplo para ilustrar este proceso.

Para que los modelos entiendan el texto y lo conviertan en vectores (esos códigos numéricos o embeddings), no podemos simplemente lanzar el texto en bruto. Si hechas las verduras enteras con todo y tierra a la olla, la sopa quedará horrible. Aquí tienes cómo se limpia y simplifica el texto usando el ejemplo de la preparación de la sopa en la cocina. De la Cocina al Código: Preparando los Datos 1. Tokenización (Cortar los ingredientes): Paso 1: Fragmentación. No te comes una tableta de chocolate entera ni una cebolla de un solo bocado. En el texto, tokenizar es picar las oraciones en pedacitos manejables (palabras o sílabas).
  • En la cocina: Cortar la zanahoria en cubitos.
  • En los datos: "La sopa está rica" se convierte en ["La", "sopa", "está", "rica"].
2. Limpieza de Ruido (Quitar las cáscaras y la tierra): Paso 2: Filtrado. Hay partes del texto que no aportan sabor (significado) y solo ensucian el modelo. Eliminamos caracteres especiales, etiquetas HTML, emojis irrelevantes o mayúsculas estorbosas.
  • En la cocina: Pelar las papas y lavar los vegetales para quitar la tierra.
  • En los datos: "¡Sopa al 100%!!!" se limpia a "sopa al 100".
3. Stop Words (Descartar el agua de lavado): Paso 3: Eliminación de conectores. Las stop words son palabras altísimas en frecuencia pero bajísimas en significado, como "el", "la", "de", "un". Si el modelo ve demasiados conectores, se distrae del ingrediente principal.
  • En la cocina: Escurrir el agua donde lavaste las verduras; no la quieres en el caldo final.
  • En los datos: ["la", "sopa", "de", "tomate"] se reduce a los elementos clave: ["sopa", "tomate"].
4. Lematización o Stemming (Reducir al sabor base): Paso 4: Normalización. Para la sopa, no importa si la zanahoria era grande, pequeña, rallada o en rodajas: al final, aporta el sabor de la zanahoria. En texto, llevamos las palabras a su raíz gramatical para que el modelo entienda que son lo mismo.
  • En la cocina: Concentrar los ingredientes en su esencia pura.
  • En los datos: Las palabras "cocinando", "cocinó" y "cocina" se unifican en su raíz: "cocinar".
El plato fuerte: Una vez que tienes tus ingredientes picados, limpios, sin basura y normalizados en la olla, es cuando el algoritmo hace su magia. Toma esa "esencia" y la convierte en un embedding (un vector de números), que no es más que la receta matemática que define el perfil de sabor exacto de tu texto.
Es una forma sencilla de cómo entender este complejo proceso que se debe llevar a cabo antes de convertir un dato cualquiera, en un vector.

Recuerda que en Oracle AI Database 26ai, los datos tipo vector son nativos. El tipo de dato vectorial, se especifica con la palabra VECTOR y los parámetros (dimensión, formato).

El tamaño máximo de una dimensión es de 65.536 y soporta los tipos de formato:
  • INT8,
  • BINARY,
  • FLOAT32 (valor de facto) y
  • FLOAT64.
La precisión de la dimensión puede ser omitida utilizando un asterisco (*,FLOAT32), para definir un valor variable o no especificado para la cantidad de dimensiones.

miércoles, 20 de mayo de 2026

J C R Licklite -Red Intergaláctica de Computadoras, 1963

 


Leyendo un aporte del Sr. Erick Murillo del medio CRHOY.com, sobre una entrevista realizada a unos de los creadores de Internet, el Dr. Steve Crocker; menciona a J C R Lickliter -Joseph Carl Robnett Licklider- de ahí las iniciales. 😅 sobre un concepto adelantado al tiempo al que él llamó: “Intergalactic Computer Network” (“Red Intergaláctica de Computadoras”), una visión que surgió entre 1962 y 1963.

No era realmente un documento formal. Eran varios documentos internos de ARPA/IPTO, dentro de los cuáles destacó el memo dirigido a los: "Members and Affiliates of the Intergalactic Computer Network" en abril de 1963, hace 63 años, tomen el numero para el sorteo de mañana.

Licklider imaginó un mundo donde:
  • Las computadoras estarían interconectadas globalmente.
  • Las personas podrían acceder a programas y datos desde cualquier lugar.
  • La información sería compartida entre gobiernos, universidades, -empresas e individuos.
  • Existiría una especie de “biblioteca universal digital”.
  • La interacción con la información sería en tiempo real y colaborativa.
Lo especial de estas ideas, es que plantearon en una época en donde la mayoría de las computadoras, eran los viejos mainframes que mantenían los datos en islas de información, el modo de procesar los datos era por lotes, mucha de la data de INPUT era con tarjetas perforadas y por supuesto, no existían redes globales, ni mucho menos computadoras personales.

Todo el documento es una joya maravillosa, pero lo que deseo resaltar hoy, es esa simbiosis humano-computadora de Licklider, que no veía la computadora solamente como una calculadora, sino como una extensión intelectual del ser humano. Esto lo desarrolló también en su trabajo, "Man–Computer Symbiosis", donde proponía colaboración estrecha entre humanos y máquinas inteligentes.

Trayendo ese pensamiento a nuestros tiempos, podríamos relacionarlo directamente con los temas de IA generativa, agentes inteligentes, interfaces conversacionales y sistemas de inteligencia artificial aumentada.

La visión de Licklider fue extraordinariamente precisa, para una época donde ni siquiera existían redes comerciales. Su idea de una “red intergaláctica” no era literalmente espacial; era una metáfora para una red universal de conocimiento e interacción humana.

Crónica del Scriptorium Datarum — Año Domini MCCLXXVI

 


Redactado bajo el ingenio de OpenAI, conforme al promptum requerido por el noble peticionario.

“Oíd, sabios del reino y guardianes de los pergaminos eternos, pues grande maravilla ha descendido sobre las cámaras del conocimiento. Los monjes calculistas de la Orden Oracle han forjado la portentosa Oracle AI Database XXVIai, artefacto de razón mecánica y memoria infinita.

Ya no habrán los escribanos de recorrer millares de códices en busca de verdad oculta, pues la máquina vectorial reconoce patrones como el astrólogo reconoce las estrellas del firmamento. Con solo invocar consulta en lengua sacra de SQL, responde el Oráculo en un instante menor al parpadeo de una vela.

Dicen los custodios del archivo que la inteligencia autónoma vigila día y noche los índices y tablas del reino, corrigiendo yerros, ordenando manuscritos y descubriendo anomalías antes que el caos alcance los registros imperiales.

Grande es también su virtud para unir documentos, grafos y relaciones bajo un único códice convergente, como si todos los saberes de Alejandría morasen en una sola biblioteca encantada.

En las bóvedas del Scriptorium, los nodos computacionales rugen como dragones dormidos, enfriados por corrientes de piedra y custodiados por caballeros de datos. Sobre el altar lumínico flotan hologramas azules, visiones arcanas donde los vectores danzan como constelaciones celestes.

Así proclama la Orden:
“Non solum data servamus… sed intelligentiam ex eis evocamus.”
“No solo preservamos los datos… sino que despertamos la inteligencia contenida en ellos.”

Y quienes dominaren tal ciencia, gobernarán el conocimiento de los siglos venideros.”

#OracleAIDatabase26ai

martes, 19 de mayo de 2026

La importancia del tamaño del chunk y el overlap a la hora de generar embeddings al procesar documentos PDF.


En el contexto de procesamiento de documentos PDF para generar embeddings y almacenar información vectorial (por ejemplo en Oracle AI Vector Search, LangChain o motores RAG), el siguiente fragmento de un script en Python, define cómo se va a “fragmentar” el texto antes de convertirlo en vectores.

El código en cuestión:
 
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=150
)


Corresponde a un objeto de LangChain utilizado para dividir texto grande en bloques más pequeños (“chunks”).
 
¿Qué significa cada parámetro?
 
chunk_size=1000
Define el tamaño máximo de cada fragmento.

En este caso:
  • Cada chunk tendrá aproximadamente 1000 caracteres.
  • No necesariamente son 1000 palabras.
  • Normalmente incluye espacios, saltos de línea y signos de puntuación.
Ejemplo conceptual:
  • Chunk 1 -> caracteres 1 al 1000
  • Chunk 2 -> caracteres 851 al 1850
  • Chunk 3 -> caracteres 1701 al 2700
chunk_overlap=150

Define cuánto contenido se repite entre un chunk y el siguiente.
Aquí: Los últimos 150 caracteres del chunk anterior se copian al siguiente chunk.
Esto evita pérdida de contexto semántico.

Ejemplo:
Chunk 1:
"...Oracle Database permite trabajar con datos vectoriales y embeddings..."

Chunk 2:
"...datos vectoriales y embeddings son utilizados para búsquedas semánticas..."

La frase compartida ayuda a mantener continuidad contextual.
 
¿Por qué esto es importante en embeddings?

Cuando conviertes texto a embeddings:

Cada chunk se transforma en un vector independiente.
Si el corte es muy agresivo:
    1. se pierde contexto,
    2. disminuye precisión semántica,
    3. empeoran las búsquedas RAG.
El overlap ayuda a preservar relaciones entre conceptos.
 
¿Qué hace “RecursiveCharacterTextSplitter”?

No corta simplemente cada 1000 caracteres de forma brutal.
El algoritmo intenta dividir respetando jerarquías:
  • párrafos
  • saltos de línea
  • oraciones
  • espacios
  • caracteres
Por eso se llama “Recursive”.
Intenta mantener fragmentos semánticamente coherentes.
 
Ejemplo práctico

Supongamos este texto:
Oracle Database 26ai incorpora capacidades avanzadas de IA.
Las búsquedas vectoriales permiten similitud semántica.
Los embeddings pueden generarse desde texto, imágenes y audio.

Con:
chunk_size=50
chunk_overlap=10

Podría producir:
Chunk 1:
Oracle Database 26ai incorpora capacidades

Chunk 2:
capacidades avanzadas de IA.
Las búsquedas

Chunk 3:
búsquedas vectoriales permiten similitud

Observe cómo “capacidades” y “búsquedas” se repiten parcialmente.
 
¿Cómo elegir los tamaños correctos?

Depende del modelo de embeddings y del tipo de documento.
 
Valores típicos

Tipo documento chunk_sizeoverlap
  • Manual técnico 800-1500 100-200
  • Código fuente 300-800 50-100
  • PDFs legales 1500-2500 200-400
  • FAQ/chatbot 300-600 50-80
Riesgos de usar chunks muy pequeños

Si haces:
chunk_size=100

Puedes destruir contexto:
"Oracle Database soporta"
"vector embeddings usando"
"AI Vector Search..."

Eso genera embeddings pobres.
 
Riesgos de chunks demasiado grandes

Si haces:
chunk_size=10000

Puedes:
  •  exceder límites del modelo,
  • aumentar costo,
  • reducir precisión de recuperación,
  • mezclar demasiados temas en un solo vector.

domingo, 17 de mayo de 2026

docker login container-registry.oracle.com: Error Response unauthorized: Auth failed.

 

[root@serverprod01 opc]# docker login container-registry.oracle.com Username: rvargasq@grupoimprosa.com Password: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Error response from daemon: Get "https://container-registry.oracle.com/v2/": unauthorized: Auth failed.

Cuando ejecutas el comando anterior, lo que deseas es autenticarse contra el registro oficial de contenedores de Oracle: Oracle Container Registry

Este registro contiene imágenes oficiales Docker/OCI de productos Oracle como:
  • Oracle Database 19c
  • Oracle AI Database 26ai
  • Oracle Linux
  • WebLogic Server
  • GraalVM
  • Java/OpenJDK
  • ORDS
  • APEX
  • etc.
Internamente lo que sucede es
  1. Solicita usuario y contraseña.
  2. Envía las credenciales al Oracle Container Registry.
  3. Si son válidas:
    • genera un token de autenticación
    • almacena credenciales localmente en Linux en ~/.docker/config.json
Esto permite ejecutar posteriormente otros comandos.

¿Por qué Oracle requiere login?

A diferencia de Docker Hub público, Oracle exige autenticación porque:
  • Debe aceptar términos de licencia específicos.
  • Algunas imágenes requieren permisos comerciales.
  • Oracle controla métricas de descarga y acceso.

Sin embargo, cuando ejecutas este comando que te solicita el usuario y la contraseña, genera un error de validación, aún cuando ambos estén correctos.

La causa de esto se observa a la hora de ingresar por el navegador en el sitio web:

Hay un mensaje que nos dice, que el acceso a DOCKER/PODMAN ya no va a permitir utilizar contraseñas de tipo SSO y que debe utilizar "Auth Token" asociado a tu cuenta de usuario.

Cuando ingresas al sitio web, al dar click sobre el nombre de tu cuenta, se va a desplegar un menú en donde podrás ir a una opción, que te permite generar el token requerido para hacer login.


Una vez que haces click sobre la opción, puedes darle al botón de generar un nuevo token. En caso de que la pierdas, puedes borrarla y volverla a crear.

Con el token en tu poder, a la hora de hacer login en el repositorio, te pide tu cuenta (generalmente tu correo electrónico) y luego cuando te solicita la contraseña, debes ingresar el token generado.

[root@serverprod01 ~]# docker login container-registry.oracle.com

Username: ronald.vargas.quesada@gmail.com
Password:

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

Ahora puedes observar que el acceso ha sido satisfactorio, pero tienes un mensaje de "Advertencia", que te indica que la credencial otorgada ha sido almacenada en un archivo de formato JSON en una ruta específica de tu $HOME, pero la misma no esta encriptada, lo que representa una exposición de seguridad.

Si ingresas a la ruta indicada en el mensaje, podrás validar efectivamente lo que te indica el mismo.

También puedes validar el formato del archivo con el comando "jq",

[root@serverprod01 .docker]# jq . config.json
{
"auths": {
"container-registry.oracle.com": {
"auth": "cm********************tZG94azYydHNs"
}
}
}

Nuestro objectivo ahora es ver como hacemos que esto se convierta en algo seguro.

Para poder utilizar un método de encriptación de estas llaves de acceso al respositorio, vamos a necesitar algunos paquetes adicionales.

Primero que todo, validar, si el paquete docker-credential-pass esta instalado:

[root@serverprod01 .docker]# which docker-credential-pass
/usr/bin/which: no docker-credential-pass in (/opt/sqlcl/bin:/root/.local/bin:/root/bin:/usr/share/Modules/bin:/sbin:/bin:/usr/sbin:/usr/bin)

Si no aparece instalado y lo quieres instalar desde los repositorios actuales, vas a obtener el siguiente mensaje de error, ya que el mismo no forma de facto parte de los repositorios.

[root@serverprod01 .docker]# dnf install -y docker-credential-helpers
Last metadata expiration check: 1:16:41 ago on Sun 17 May 2026 02:47:35 AM GMT.
No match for argument: docker-credential-helpers
Error: Unable to find a match: docker-credential-helpers

Primero vamos a necesitar algunas dependencias si queremos hacer la instalación desde un git directo del paquete.

[root@serverprod01 .docker]# dnf install golang-github-docker-credential-helpers-devel
Last metadata expiration check: 0:01:25 ago on Sun 17 May 2026 04:05:58 AM GMT.
Dependencies resolved.
=====================================================================
 Package                                           Arch       Version                    Repository                  Size
=====================================================================
Installing:
 golang-github-docker-credential-helpers-devel     noarch     0.6.3-13.el10_0            ol10_u1_developer_EPEL      52 k
Installing dependencies:
 glib2-devel                                       x86_64     2.80.4-10.el10_1.13        ol10_appstream             1.8 M
 gnutls-c++                                        x86_64     3.8.10-3.el10_1            ol10_appstream              31 k
 gnutls-dane                                       x86_64     3.8.10-3.el10_1            ol10_appstream              42 k
 gnutls-devel                                      x86_64     3.8.10-3.el10_1            ol10_appstream             3.4 M
 go-filesystem                                     x86_64     3.6.0-8.el10_1             ol10_appstream              11 k
 libblkid-devel                                    x86_64     2.40.2-16.el10_1           ol10_appstream             106 k
 libffi-devel                                      x86_64     3.4.4-10.el10              ol10_appstream              46 k
 libidn2-devel                                     x86_64     2.3.7-3.el10               ol10_appstream             109 k
 libmount-devel                                    x86_64     2.40.2-16.el10_1           ol10_appstream             102 k
 libsecret-devel                                   x86_64     0.21.2-8.el10              ol10_appstream             492 k
 libselinux-devel                                  x86_64     3.9-1.el10                 ol10_appstream             342 k
 libsepol-devel                                    x86_64     3.9-1.el10                 ol10_appstream              89 k
 libtasn1-devel                                    x86_64     4.20.0-1.el10              ol10_appstream             131 k
 libtasn1-tools                                    x86_64     4.20.0-1.el10              ol10_appstream              43 k
 p11-kit-devel                                     x86_64     0.25.5-7.el10              ol10_appstream             129 k
 pcre2-devel                                       x86_64     10.44-1.0.1.el10.3         ol10_appstream             693 k
 pcre2-utf16                                       x86_64     10.44-1.0.1.el10.3         ol10_appstream             226 k
 pcre2-utf32                                       x86_64     10.44-1.0.1.el10.3         ol10_appstream             214 k
 sysprof-capture-devel                             x86_64     47.2-1.el10                ol10_appstream              71 k
 unbound-libs                                      x86_64     1.20.0-18.el10_1           ol10_appstream             588 k
Installing weak dependencies:
 unbound-anchor                                    x86_64     1.20.0-18.el10_1           ol10_appstream              74 k

Transaction Summary
=====================================================================
Install  22 Packages

Total download size: 8.8 M
Installed size: 31 M
Is this ok [y/N]: y
Downloading Packages:
(1/22): golang-github-docker-credential-helpers-devel-0.6.3-13.el10_0.noarch.rpm          402 kB/s |  52 kB     00:00
(2/22): gnutls-c++-3.8.10-3.el10_1.x86_64.rpm                 139 kB/s |  31 kB     00:00
(3/22): glib2-devel-2.80.4-10.el10_1.13.x86_64.rpm            7.3 MB/s | 1.8 MB     00:00
(4/22): gnutls-dane-3.8.10-3.el10_1.x86_64.rpm                258 kB/s |  42 kB     00:00
(5/22): go-filesystem-3.6.0-8.el10_1.x86_64.rpm                87 kB/s |  11 kB     00:00
(6/22): gnutls-devel-3.8.10-3.el10_1.x86_64.rpm                13 MB/s | 3.4 MB     00:00
(7/22): libblkid-devel-2.40.2-16.el10_1.x86_64.rpm            539 kB/s | 106 kB     00:00
(8/22): libffi-devel-3.4.4-10.el10.x86_64.rpm                 335 kB/s |  46 kB     00:00
(9/22): libidn2-devel-2.3.7-3.el10.x86_64.rpm                 1.2 MB/s | 109 kB     00:00
(10/22): libmount-devel-2.40.2-16.el10_1.x86_64.rpm           901 kB/s | 102 kB     00:00
(11/22): libsepol-devel-3.9-1.el10.x86_64.rpm                 810 kB/s |  89 kB     00:00
(12/22): libsecret-devel-0.21.2-8.el10.x86_64.rpm             2.3 MB/s | 492 kB     00:00
(13/22): libselinux-devel-3.9-1.el10.x86_64.rpm               1.2 MB/s | 342 kB     00:00
(14/22): p11-kit-devel-0.25.5-7.el10.x86_64.rpm               1.1 MB/s | 129 kB     00:00
(15/22): libtasn1-tools-4.20.0-1.el10.x86_64.rpm              166 kB/s |  43 kB     00:00
(16/22): libtasn1-devel-4.20.0-1.el10.x86_64.rpm              405 kB/s | 131 kB     00:00
(17/22): pcre2-utf16-10.44-1.0.1.el10.3.x86_64.rpm            1.7 MB/s | 226 kB     00:00
(18/22): sysprof-capture-devel-47.2-1.el10.x86_64.rpm         675 kB/s |  71 kB     00:00
(19/22): pcre2-devel-10.44-1.0.1.el10.3.x86_64.rpm            2.4 MB/s | 693 kB     00:00
(20/22): pcre2-utf32-10.44-1.0.1.el10.3.x86_64.rpm            911 kB/s | 214 kB     00:00
(21/22): unbound-libs-1.20.0-18.el10_1.x86_64.rpm             5.6 MB/s | 588 kB     00:00
(22/22): unbound-anchor-1.20.0-18.el10_1.x86_64.rpm           420 kB/s |  74 kB     00:00
----------------------------------------------------------------------------------------------
Total                                                         6.2 MB/s | 8.8 MB     00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                      1/1
  Running scriptlet: unbound-libs-1.20.0-18.el10_1.x86_64                1/22
  Installing       : unbound-libs-1.20.0-18.el10_1.x86_64                1/22
  Installing       : unbound-anchor-1.20.0-18.el10_1.x86_64              2/22
  Running scriptlet: unbound-anchor-1.20.0-18.el10_1.x86_64              2/22
Created symlink '/etc/systemd/system/timers.target.wants/unbound-anchor.timer' → '/usr/lib/systemd/system/unbound-anchor.timer'.

  Installing       : gnutls-dane-3.8.10-3.el10_1.x86_64                     3/22
  Installing       : sysprof-capture-devel-47.2-1.el10.x86_64               4/22
  Installing       : pcre2-utf32-10.44-1.0.1.el10.3.x86_64                  5/22
  Installing       : pcre2-utf16-10.44-1.0.1.el10.3.x86_64                  6/22
  Installing       : pcre2-devel-10.44-1.0.1.el10.3.x86_64                  7/22
  Installing       : p11-kit-devel-0.25.5-7.el10.x86_64                     8/22
  Installing       : libtasn1-tools-4.20.0-1.el10.x86_64                    9/22
  Installing       : libtasn1-devel-4.20.0-1.el10.x86_64                   10/22
  Installing       : libsepol-devel-3.9-1.el10.x86_64                      11/22
  Installing       : libselinux-devel-3.9-1.el10.x86_64                    12/22
  Installing       : libidn2-devel-2.3.7-3.el10.x86_64                     13/22
  Installing       : libffi-devel-3.4.4-10.el10.x86_64                     14/22
  Installing       : libblkid-devel-2.40.2-16.el10_1.x86_64                15/22
  Installing       : libmount-devel-2.40.2-16.el10_1.x86_64                16/22
  Installing       : glib2-devel-2.80.4-10.el10_1.13.x86_64                17/22
  Installing       : go-filesystem-3.6.0-8.el10_1.x86_64                   18/22
  Installing       : gnutls-c++-3.8.10-3.el10_1.x86_64                     19/22
  Installing       : gnutls-devel-3.8.10-3.el10_1.x86_64                   20/22
  Installing       : libsecret-devel-0.21.2-8.el10.x86_64                                        21/22
  Installing       : golang-github-docker-credential-helpers-devel-0.6.3-13.el10_0.noarch        22/22
  Running scriptlet: golang-github-docker-credential-helpers-devel-0.6.3-13.el10_0.noarch        22/22

Installed:
  glib2-devel-2.80.4-10.el10_1.13.x86_64       gnutls-c++-3.8.10-3.el10_1.x86_64
  gnutls-dane-3.8.10-3.el10_1.x86_64           gnutls-devel-3.8.10-3.el10_1.x86_64
  go-filesystem-3.6.0-8.el10_1.x86_64          golang-github-docker-credential-helpers-devel-0.6.3-13.el10_0.noarch
  libblkid-devel-2.40.2-16.el10_1.x86_64       libffi-devel-3.4.4-10.el10.x86_64
  libidn2-devel-2.3.7-3.el10.x86_64            libmount-devel-2.40.2-16.el10_1.x86_64
  libsecret-devel-0.21.2-8.el10.x86_64         libselinux-devel-3.9-1.el10.x86_64
  libsepol-devel-3.9-1.el10.x86_64             libtasn1-devel-4.20.0-1.el10.x86_64
  libtasn1-tools-4.20.0-1.el10.x86_64          p11-kit-devel-0.25.5-7.el10.x86_64
  pcre2-devel-10.44-1.0.1.el10.3.x86_64        pcre2-utf16-10.44-1.0.1.el10.3.x86_64
  pcre2-utf32-10.44-1.0.1.el10.3.x86_64        sysprof-capture-devel-47.2-1.el10.x86_64
  unbound-anchor-1.20.0-18.el10_1.x86_64       unbound-libs-1.20.0-18.el10_1.x86_64

Complete!

Ahora vamos con el paquete en si.

[root@serverprod01 .docker]# cd /tmp
[root@serverprod01 tmp]# curl -LO https://github.com/docker/docker-credential-helpers/releases/download/v0.9.3/docker-credential-pass-v0.9.3.linux-amd64

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 2068k  100 2068k    0     0  13.5M      0 --:--:-- --:--:-- --:--:-- 13.5M
[root@serverprod01 tmp]# ls -lat
total 320436
-rw-r--r--.  1 root root   2117784 May 17 04:14 docker-credential-pass-v0.9.3.linux-amd64
drwxrwxrwt. 15 root root      4096 May 17 04:14 .
drwxr-xr-x.  2 root root        19 May 17 00:28 hsperfdata_root
drwxr-xr-x.  2 root root        64 May 17 00:07 META-INF
....
agent
drwxr-xr-x.  6 root root      4096 May  7 12:18 apex

Agregamos permisos al paquete descargado y lo movemos a nuestra ruta de binarios ejecutables.

[root@serverprod01 tmp]# chmod +x docker-credential-pass-v0.9.3.linux-amd64

[root@serverprod01 tmp]# mv docker-credential-pass-v0.9.3.linux-amd64 /usr/local/bin/docker-credential-pass

[root@serverprod01 tmp]# uname -a
Linux serverprod01 6.12.0-202.76.4.2.el10uek.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 13 01:27:49 PDT 2026 x86_64 GNU/Linux

[root@serverprod01 tmp]# uname -m
x86_64

Verificamos nuestra ruta de binarios en las variables de ambiente.

[root@serverprod01 tmp]# echo $PATH
/opt/sqlcl/bin:/root/.local/bin:/root/bin:/usr/share/Modules/bin:/sbin:/bin:/usr/sbin:/usr/bin

Creamos un link al ejecutable en un directorio de ruta.

[root@serverprod01 tmp]# ln -s /usr/local/bin/docker-credential-pass /usr/bin/docker-credential-pass

Y ahora verificamos que si se encuentra el paquete y que es posible ser ejecutado.

[root@serverprod01 tmp]# which docker-credential-pass
/bin/docker-credential-pass
[root@serverprod01 tmp]# docker-credential-pass version
docker-credential-pass (github.com/docker/docker-credential-helpers) v0.9.3

Vamos a generar ahora el conjunto de llaves.
Debes escoger como opciones:
  1. RSA and RSA
  2. 4096 para los bits de largo
  3. Que la llave no expire
RSA cryptosystem es uno de los algoritmos de criptografía asimétrica más importantes y utilizados desde 1977, que fue creada. La idea fundamental con RSA es que:
  • cualquiera puede tener tu llave pública,
  • pero solo vos poseés la llave privada.
Entonces:
  • Public Key → cifra
  • Private Key → descifra
El tamaño estandar de las llaves es 2048 y el valor de facto que te propone la configuración es 3072, pero nosotros estamos utilizando 4096 para que sea más seguro.

[root@serverprod01 tmp]# gpg --full-generate-key
gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

Cuando indiques que la información es correcta, te va a aparecer una ventana en donde debes ingresar una contraseña para proteger la boveda de claves.

Listo ahora te brinda la información de lo que contiene la boveda de claves creada.

GnuPG needs to construct a user ID to identify your key.

Real name: Docker Registry Credentials
Email address: ronald.vargas.quesada@gmail.com
Comment: Administrador
You selected this USER-ID:
    "Docker Registry Credentials (Administrador) <ronald.vargas.quesada@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/0569B431B2BDE499CA5F8D4B957AA628DEC7383D.rev'
public and secret key created and signed.

pub   rsa4096 2026-05-17 [SC]
      0569B431B2BDE499CA5F8D4B957AA628DEC7383D
uid                      Docker Registry Credentials (Administrador) <ronald.vargas.quesada@gmail.com>
sub   rsa4096 2026-05-17 [E]

En la última línea debe existir esa "E" entre los paréntesis cuadrados, esto indica que las llaves que se almacenen en la bodega estarán encriptadas.

Ahora podemos validar la boveda creada, listando las llaves disponibles.

[root@serverprod01 tmp]# gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
/root/.gnupg/pubring.kbx
------------------------

sec   rsa4096/957AA628DEC7383D 2026-05-17 [SC]
      0569B431B2BDE499CA5F8D4B957AA628DEC7383D
uid                 [ultimate] Docker Registry Credentials (Administrador) <ronald.vargas.quesada@gmail.com>
ssb   rsa4096/0B4F776423A261D3 2026-05-17 [E]

En la información anterior en la sección de "sec" el valor que esta despues de rsa4096
[root@serverprod01 tmp]# pass init 957AA628DEC7383D
mkdir: created directory '/root/.password-store/'
Password store initialized for 957AA628DEC7383D

Hacemos una prueba de encriptación.

[root@serverprod01 tmp]# echo "test" | gpg --encrypt --armor -r 957AA628DEC7383D
-----BEGIN PGP MESSAGE-----

hQIMAwtPd2QjomHTARAAl7u47hWj4GvGMKrt0uAFRQK6yILRfXjNN+usbwmkHBTg
d2g7AmT+tItZI6I/i/4mZ5EGyebHZ36ErgpNAFbZRuPihFeKLrxFzbsKg3Qmk2f3
lVlPrQGEuYiaagu+wY8M7jBBWeEd/HWOKPmHwzlVSTiFXv+gygRWa8jrkp1r8egG
pnmzSJYcPIufHmeIDO7VrI2RGdf3a1KQbhX9MwG8kcWOrpAkmXVNVzTtXB8X5IZ2
9qhgo595YbaAlDltYDQgDKgc2rQv06Ya5OakqBeeMGcE9KOGpPAVm5nbmqw9g4IS
JIhbrrxfXhNBDYj1IpkiGp+i7Urmz9FuvOdiLd5vJdaCwStgL3cgr5K0f0InaxCh
pPUVFMS163ctoUslkOLbSt8eYyrMAbACgnYNjypdmDWq3MpZIliKoscoosZi7aGq
S2Vl1brFQT9eywEwnrNjcZy/7MZBltShBeZoDo+zlKgfbDbFu1dT/AB7juk1sc8B
ttSvMQcxuQitVF1GDBPyt7jvQ7WncKDMYrqhHlw1LOUwcRWvmXqxDesAaxZiFn9x
maeLlTTJ2lzCza/W0U9LNvnD2r+69ED7ieEe/9MFCnyk4dmYe8pVgWiHHxWoYTg6
D8MnjgycDvkTQ1TP8TX92jbpmq/6ZiAo4MyZHGx/QJaJdGFe22/FWrsDu/gSr6nU
SgEJAhDCTUX7hd9KyvVOrfcTob2bilsv3u37d1eu5uSG5/vNDIIWuiDenJ5f9Hbu
4E5rpq19xBj+RwrkgRjaXGhioYB2j7e4pwVI
=+/2N
-----END PGP MESSAGE-----

Ahora necesitamos hacer unos ajustes en el archivo en donde guardabamos inicialmente las claves del Oracle Container Registry, para que utilice el nuevo repositorio y no guarde ahí la Token en texto plano.

[root@serverprod01 tmp]# cd
[root@serverprod01 ~]# cd .docker/
[root@serverprod01 .docker]# cat config.json
{
        "credsStore": "pass"
}

Procedemos a deslogearnos del repositorio.

[root@serverprod01 .docker]# docker logout container-registry.oracle.com
Removing login credentials for container-registry.oracle.com

Ahora nos volvemos a logear.

[root@serverprod01 .docker]# docker login container-registry.oracle.com
Username: ronald.vargas.quesada@gmail.com
Password:
Login Succeeded

Ahora estamos recibiendo el mensaje de logeo satisfactorio y no tenemos el mensaje de "Advertencia" inicial.

Puedes validar ahora el archivo en donde se encuentraba el texto plano del token y verás que se mantiene el cambio que realizamos.

[root@serverprod01 .docker]# ls -lat
total 8
drwx------.  2 root root   25 May 17 17:04 .
-rw-------.  1 root root   79 May 17 17:04 config.json
dr-xr-x---. 11 root root 4096 May 17 17:02 ..
[root@serverprod01 .docker]# cat config.json
{
        "auths": {
                "container-registry.oracle.com": {}
        },
        "credsStore": "pass"
}

Veamos que guarda en la ruta de creación de la boveda de seguridad encriptada.

[root@serverprod01 .docker]# ls -lat /root/.password-store
total 8
drwx------.  3 root root   54 May 17 17:04 .
drwx------.  3 root root   54 May 17 17:04 docker-credential-helpers
dr-xr-x---. 11 root root 4096 May 17 17:02 ..
-rw-------.  1 root root   17 May 17 17:02 .gpg-id
[root@serverprod01 .docker]# ls -lat /root/.password-store/docker-credential-helpers
total 0
drwx------. 2 root root 49 May 17 17:04 'Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20='
drwx------. 3 root root 54 May 17 17:04  .
drwx------. 3 root root 54 May 17 17:04  ..

[root@serverprod01 docker-credential-helpers]# ls -lat
total 0
drwx------. 2 root root 49 May 17 17:04 'Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20='
drwx------. 3 root root 54 May 17 17:04  .
drwx------. 3 root root 54 May 17 17:04  ..

[root@serverprod01 docker-credential-helpers]# cd *Y*

[root@serverprod01 Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20=]# pwd
/root/.password-store/docker-credential-helpers/Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20=

[root@serverprod01 Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20=]# ls -lat
total 4
drwx------. 2 root root  49 May 17 17:04 .
-rw-------. 1 root root 610 May 17 17:04 ronald.vargas.quesada@gmail.com.gpg
drwx------. 3 root root  54 May 17 17:04 ..
[root@serverprod01 Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20=]# cat ronald.vargas.quesada@gmail.com.gpg

Owd#▒a▒▒`▒".|▒լf'▒▒▒2▒▒▒1▒▒o▒▒▒▒
▒▒$0▒▒▒▒N[▒O▒6  {Dؾ▒▒▒5▒N▒▒.▒▒▒1▒▒B)▒▒▒▒▒\▒4▒▒▒▒▒▒*)؉I▒▒▒▒7▒▒lj▒▒▒▒i"▒qLj▒▒r▒k▒j▒/5▒UC▒▒x▒▒e▒     ▒Q▒▒▒K▒y▒rÓ▒▒H?
▒▒▒(▒▒▒▒J▒▒'▒▒▒EVh▒▒    ▒▒▒G▒z▒%▒I▒HW"▒▒`&▒▒E▒
▒P!/Mh▒w▒8(I=߀▒g▒2?1f▒▒F.a▒▒▒▒▒P7▒`▒▒▒k▒X▒'▒y▒▒▒v▒▒f▒L7n▒▒l7▒▒▒▒▒^▒▒▒Zc▒EhG▒H▒TO▒ȏO▒▒▒ej
x▒▒an▒j▒▒w▒d-▒▒▒▒ g ▒t*5▒>▒▒▒▒▒u%▒4▒▒t▒-y▒A$▒▒▒/#v▒▒▒▒▒s
▒▒=lM▒I\▒▒g&;▒▒▒K|hi▒▒▒*▒=▒▒+▒▒▒i▒▒
▒▒k▒▒▒:▒▒~FW▒▒▒▒&▒▒T▒
                        ▒▒▒▒hd▒▒▒▒qm▒▒'▒▒▒E▒▒Bv}ꄽ▒~▒U▒▒,▒▒Q    8\~      ▒▒5▒▒▒▒i&MÕ▒mv▒▒~B>▒▒▒5▒▒▒▒b[!I▒3▒h▒N6▒▒O▒▒+▒,▒▒xV▒\L
{d[root@serverprod01 Y29udGFpbmVyLXJlZ2lzdHJ5Lm9yYWNsZS5jb20=]# PuTTYPuTTY

Como pueden observar, ya tenemos protegida esta información y la exposición de seguridad, ha sido resuelta.


Recuerden que siempre es de vital importancia cuando implementan cualquier funcionalidad, validar que no se creen brechas se seguridad, por el mal empleo o configuración de algún paquete o funcionalidad.




sábado, 16 de mayo de 2026

Oracle AI Database 26ai-FREE con APEX 26.1 ejecutándose en DOCKER sobre Oracle Linux UEK10: Porqué el kernel UEK?



Productiva tarde del sábado, invirtiéndo 3 horas y media, en crear un ambiente de Oracle AI Database 26ai Free, APEX 26.1 y ORDS ejecutándose en un docker en un servicio desplegado en la nube de Oracle -OCI- con 1 OCPU, 12 GB RAM y 200GB de bootdisk.

Eso si para hacerlo más interesante, mi servicio estaba en Oracle Linux V9.7 ya que lo había creado hace unos días atrás, entonces antes procedí a migrar a Oracle Linux 10 utilizando LEAPP - "Legacy Application".

Un detalle interesante, es que la herramienta no soporta una migración hacia Oracle Linux 10, desde Oracle Linux 9, si el kernel que se utiliza de facto, no es UEK.

Cuando ejecutas el comando: uname -a, puedes validar si utilizas:
  • -UEK (Unbreakable Enterprise Kernel)
  • -RHCK (Red Hat Compatible Kernel)
Si el kernel de facto es compatible con el sombrero rojo y ejecutas la prevalidación de la migración con la herramienta LEAPP, te aparece dentro de los inhibidores el siguiente:

Risk Factor: high (inhibitor)
Title: BTRFS used, confirm UEK as default boot kernel in OL9
Summary: Upgrade process was interrupted because btrfs is enabled and need to confirm UEK as default boot kernel in OL9
Remediation: [hint] Confirm UEK kernel install and default boot
Key: ba493fb6524e939f518a2448dc93aa10817ddb44


Para estar completamente seguro del kernel de facto, puedes hacer lo siguiente:

[root@serverprod01 opc]# awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg
[root@serverprod01 opc]# awk -F\' '$1=="menuentry " {print $2}' /boot/efi/EFI/redhat/grub.cfg


Luego con el comando "GRUBBY" puedes desplegar todos los kernel disponibles que puedes utilizar.

[root@serverprod01 opc]# grubby --info=ALL | grep ^kernel
kernel="/boot/vmlinuz-6.12.0-108.64.6.3.el9uek.x86_64"
kernel="/boot/vmlinuz-5.14.0-611.34.1.el9_7.x86_64"
kernel="/boot/vmlinuz-0-rescue-5317e565ff83fadfe174b7ef8815fd20"
kernel="/boot/vmlinuz-6.12.0-202.76.4.2.el9uek.x86_64"
kernel="/boot/vmlinuz-5.14.0-611.55.1.el9_7.x86_64"
kernel="/boot/vmlinuz-0-rescue-e3bea40a02e64e458672cddd21ddbb2e"

Procede a configurar el kernel UEK más moderno.

[root@serverprod01 opc]# grubby --set-default /boot/vmlinuz-6.12.0-202.76.4.2.el9uek.x86_64

The default is /boot/loader/entries/e3bea40a02e64e458672cddd21ddbb2e-6.12.0-202.76.4.2.el9uek.x86_64.conf with index 3 and kernel /boot/vmlinuz-6.12.0-202.76.4.2.el9uek.x86_64

[root@serverprod01 opc]# grubby --default-kernel

/boot/vmlinuz-6.12.0-202.76.4.2.el9uek.x86_64

[root@serverprod01 opc]#

Después de esto, ya no existe el problema con la validación del kernel.

Lo más interesante como dice un compañero de trabajo: "Hasta sirve".



miércoles, 6 de mayo de 2026

Comunicado: 4 de mayo de 2026 Actualizaciones mensuales de parches de seguridad críticos (CSPU) de Oracle a partir del 28 de mayo de 2026

 

Oracle presenta una nueva periodicidad de lanzamiento mensual para ayudar a los clientes a abordar las vulnerabilidades de seguridad críticas con mayor rapidez y reducir el riesgo de exposición.
Oracle ha enviado el siguiente correo a todos sus clientes:
A partir del 28 de mayo de 2026, Oracle publicará una Actualización de parches de seguridad críticos (CSPU) cada mes. Las CSPU están diseñadas para proporcionar correcciones de seguridad específicas y de alta prioridad en un formato más conciso y específico, lo que facilita su aplicación con mínimas interrupciones.

Estimado cliente de Oracle:

-21 de julio de 2026 (CPU)Tras el lanzamiento inicial de mayo, las CSPU se publicarán mensualmente de forma continua, coincidiendo con el tercer martes de cada mes, de acuerdo con el modelo de lanzamiento de seguridad establecido por Oracle.

Este nuevo enfoque complementa las Actualizaciones trimestrales de parches críticos (CPU) de Oracle, que continuarán publicándose de forma acumulativa. Las actualizaciones de seguridad de Oracle (CSPU) permiten a los clientes implementar correcciones específicas para vulnerabilidades críticas con mayor rapidez, sin tener que esperar al siguiente ciclo trimestral.
Las próximas cuatro fechas de lanzamiento de actualizaciones de seguridad son:
  • 28 de mayo de 2026 (CSPU)
  • 16 de junio de 2026 (CSPU)
  • 18 de agosto de 2026 (CSPU)
¿Qué significa esto para usted? • Acceso más rápido a correcciones de seguridad críticas • Actualizaciones más pequeñas y específicas • Menor riesgo y aplicación de parches simplificada para entornos gestionados por el cliente

Oracle mantiene su compromiso de ayudar a los clientes a mantener una sólida postura de seguridad mediante la entrega oportuna de actualizaciones de seguridad de alta calidad. 

Así termina el correo, pero que no se dice en el correo.? 

Es casi un 100% seguro, que para poder instalar estos CSPU's, vas a tener que contar con una versión de R.U. reciente. Al menos con el actuar de Oracle en los últimos años, sería al último CPU y eso si nos pone contra la pared tanto frente a la certificación de aplicaciones propias de Oracle, como de terceros, sin dejar de lado, el riesgo que implica hacer una instalación de CPU hoy en día, apenas esté es liberado.

Para muestra un botón con lo sucedido este trimestre. También estamos con un cambio en la aplicación de los CPUs, que voy a explicar en otro posteo, pero como dicen en el beisbol, "Dígale Adiós al OPatch".

MOS aplica requisito de contraseñas para realizar descarga de R.U. a nivel de la base de datos.

 

Dando seguimiento al tema de los cambios realizados de manera progresiva en el MOS, toca ahora, hablar de la necesidad de crear un SR, para obtener una contraseña para la descarga de los R.U. anteriores al último liberado.

Observé algunas publicaciones que son los R.U. a partir del 19.29 y verifiqué dicha información y es 100% correcta. Ya para este parche requiere la contraseña.
Antes de poder crear el SR, debes pasar un asistente de IA que tiene un coeficiente intelectual de un "lagarto cornudo" - si tienes dudas pregunta a tu IA de preferencia cuál es-, que al preguntarle que necesitas una contraseña para descargar un parche que esta protegido con contraseña, te indica que revise antes la información del README.txt, ya que no existe indicaciones de que se requiera una contraseña para descargarlo. Lógico, porque el parche fue liberado antes de la implementación y quién entreno el modelo, no sabía ese pequeño detalle.
Ahora, realmente están poniendo a pruebas nuestra paciencia.!!!
Una vez que realizas unas 5 interacciones con el asistente, el mismo se cansa y te recomienda crear un SR y te brinda la oportunidad de iniciar el flujo.

Nota curiosa, el documento de SLAs para los SR, ya no esta disponible publicamente, por lo que creo esta siendo modificada y adaptánse también para estos cambios.

Esto al menos me pareció un poco más inteligente y las primeras 3 preguntas de las 12 que realiza, las autorellena con la información que le brindaste al asistente. Luego te hace tantas preguntas, que desde mi experiencia con las versiones anteriores y para lo que se necesita concretamente en este caso, son bastante inútiles. Incluso debes agregar el OCID del ambiente en donde deseas aplicar el parche.
Con este asistente, no te permite asignar el nivel del tiquete, por lo que pienso, que le asigna un nivel 4, o sea, baja nivel de criticidad.

La notificación de la creación del SR si llegó al correo, pero aquí viene la otra parte. La creación de SR previo a este fin de semana anterior, se gestionaban por 4 niveles de criticidad. Yo podía configurar el nivel en el rango de 2 a 4. Ya para un SR nivel 1, había que escalarlo o bien escoger que era un ambiente productivo, con afectación total de los servicios.

Yo he llegado a experimentar hasta 7 días de atraso antes de obtener una respuesta. Así que la experiencia de usuario en MOS, es cada vez más difícil de defender. Hoy MOS es más burocrático y enredado de utilizar, y sinceramente, añoro la interfaz clásica que nos acompañó durante tantos años. Al finalizar de escribir esta nota, han pasado 45 minutos desde la creación del SR y aún no existe actividad alguna por parte del equipo del MOS.
Les prometo pasar el chisme de cuánto se duró, para obtener una respuesta.

Todos los Sábados a las 8:00PM