--- title: "Cómo instalar el registro Harbor en Ubuntu 24.04 con HTTPS" description: "Instala Harbor en Ubuntu 24.04 con Docker Compose, certificado de Let's Encrypt y escáner Trivy, y publica tu primera imagen en un proyecto privado con robot." category: "CI/CD DevOps" language: es source: https://cubepath.com/es/docs/ci-cd-devops/instalacion-del-registro-de-contenedores-harbor updated: 2026-09-25 --- # Cómo instalar el registro Harbor en Ubuntu 24.04 con HTTPS Harbor es un registro de contenedores de código abierto, proyecto graduado de la CNCF, que añade al registro de Docker proyectos con control de acceso por roles, análisis de vulnerabilidades con Trivy, cuentas robot para CI y replicación entre registros. En este tutorial instalarás Harbor en Ubuntu 24.04 con el instalador oficial basado en Docker Compose, lo protegerás con un certificado de Let's Encrypt que se renueva solo y publicarás tu primera imagen en un proyecto privado. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM, 2 vCPU y 40 GB libres en disco (las imágenes ocupan rápido; dimensiona según tu uso). - Un usuario no root con privilegios `sudo`. - Docker Engine y el plugin Docker Compose instalados desde el repositorio oficial de Docker. - Un dominio o subdominio, por ejemplo `registry.your_domain`, con un registro A apuntando a la IP del servidor. - Los puertos 80 y 443 libres en el servidor (sin Nginx ni Apache escuchando) y abiertos en el firewall. Comprueba que Docker y Compose están disponibles: ```bash docker --version docker compose version ``` ```output Docker version 28.x.x, build ... Docker Compose version v2.x.x ``` ## Paso 1: Obtener el certificado TLS Docker exige HTTPS para cualquier registro que no sea local, así que empieza por el certificado. Abre los puertos web en UFW: ```bash sudo ufw allow 80/tcp sudo ufw allow 443/tcp ``` Instala Certbot y solicita el certificado en modo `standalone`, en el que Certbot levanta su propio servidor temporal en el puerto 80. Funciona porque Harbor todavía no está en marcha: ```bash sudo apt update sudo apt install certbot sudo certbot certonly --standalone -d registry.your_domain ``` ```output Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/registry.your_domain/fullchain.pem Key is saved at: /etc/letsencrypt/live/registry.your_domain/privkey.pem ``` ## Paso 2: Descargar el instalador de Harbor Harbor publica dos instaladores: el **online**, que descarga las imágenes desde Docker Hub durante la instalación, y el **offline**, que las incluye en el archivo. Usa el online. Consulta la última versión estable en `https://github.com/goharbor/harbor/releases` y guárdala en una variable, sustituyendo `VERSION` por el número real con su `v` inicial (por ejemplo, con el formato `v2.x.y`): ```bash HARBOR_VERSION=VERSION ``` Descarga el instalador y descomprímelo en `/opt`: ```bash cd /tmp curl -fLO "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-online-installer-${HARBOR_VERSION}.tgz" sudo tar -xzf "harbor-online-installer-${HARBOR_VERSION}.tgz" -C /opt ls /opt/harbor ``` ```output LICENSE common.sh harbor.yml.tmpl install.sh prepare ``` ## Paso 3: Configurar harbor.yml Toda la configuración de Harbor vive en `harbor.yml`. Crea el archivo a partir de la plantilla: ```bash cd /opt/harbor sudo cp harbor.yml.tmpl harbor.yml sudo nano harbor.yml ``` Modifica estas claves (el resto puede quedarse con su valor por defecto): ```yaml hostname: registry.your_domain http: port: 80 https: port: 443 certificate: /etc/letsencrypt/live/registry.your_domain/fullchain.pem private_key: /etc/letsencrypt/live/registry.your_domain/privkey.pem harbor_admin_password: your_admin_password database: password: your_db_password data_volume: /data ``` - `hostname`: el nombre con el que accederán los clientes. Debe coincidir con el certificado. - `harbor_admin_password`: contraseña inicial del usuario `admin`. Usa una robusta; podrás cambiarla desde la interfaz. - `database.password`: contraseña de la base de datos PostgreSQL interna. Cambia el valor por defecto de la plantilla. - `data_volume`: directorio del host donde Harbor guarda imágenes, base de datos y configuración generada. Como el archivo contiene contraseñas, restringe sus permisos: ```bash sudo chmod 600 harbor.yml ``` ## Paso 4: Instalar Harbor con Trivy El script `install.sh` genera la configuración a partir de `harbor.yml` (con el script `prepare`), descarga las imágenes y arranca los contenedores con Docker Compose. La opción `--with-trivy` añade el escáner de vulnerabilidades: ```bash sudo ./install.sh --with-trivy ``` El proceso tarda unos minutos. Al final verás: ```output [Step 5]: starting Harbor ... ... ----Harbor has been installed and started successfully.---- ``` Comprueba que todos los contenedores están en marcha y sanos: ```bash sudo docker compose ps ``` Todos los servicios (`harbor-core`, `harbor-db`, `harbor-portal`, `nginx`, `redis`, `registry`, `trivy-adapter` y otros) deben aparecer como `Up` y, cuando lo tengan, `(healthy)`. Comprueba también la API de salud: ```bash curl -s https://registry.your_domain/api/v2.0/health ``` ```output {"status":"healthy","components":[{"name":"core","status":"healthy"}, ...]} ``` Los contenedores de Harbor usan la política `restart: always`, así que vuelven a arrancar solos cuando se reinicia el servidor. ## Paso 5: Crear un proyecto privado Abre `https://registry.your_domain` e inicia sesión como `admin` con la contraseña de `harbor_admin_password`. En Harbor, las imágenes se organizan en **proyectos**, que son la unidad de permisos. 1. Ve a **Projects > New Project**. 2. Escribe `myproject` como nombre y deja **Access Level** sin marcar como **Public**, para que sea privado. 3. Pulsa **OK**. 4. Entra en el proyecto, abre **Configuration** y marca **Automatically scan images on push**. Opcionalmente marca **Prevent vulnerable images from running** con severidad **Critical** para impedir que se descarguen imágenes con vulnerabilidades críticas. 5. Guarda los cambios. El proyecto `library` que ya existe es público; no subas a él imágenes internas. Para las personas, crea usuarios en **Administration > Users** y añádelos al proyecto en **Members** con el rol adecuado: **Developer** puede subir y bajar imágenes, **Guest** solo descargarlas y **Maintainer** además gestiona la configuración del proyecto. ## Paso 6: Subir la primera imagen Desde tu equipo o cualquier servidor con Docker, inicia sesión en el registro: ```bash docker login registry.your_domain ``` ```output Login Succeeded ``` Descarga una imagen pequeña, etiquétala con la ruta del proyecto y súbela: ```bash docker pull alpine:3.20 docker tag alpine:3.20 registry.your_domain/myproject/alpine:3.20 docker push registry.your_domain/myproject/alpine:3.20 ``` ```output The push refers to repository [registry.your_domain/myproject/alpine] ... 3.20: digest: sha256:... size: 528 ``` En la interfaz, entra en **Projects > myproject > Repositories**: aparece `myproject/alpine` con la etiqueta `3.20`. Como activaste el análisis al subir, la columna **Vulnerabilities** mostrará el resultado de Trivy al cabo de unos segundos. La primera vez tarda más porque Trivy descarga su base de datos de vulnerabilidades. Comprueba la descarga desde otra máquina, o borrando antes la copia local: ```bash docker image rm registry.your_domain/myproject/alpine:3.20 docker pull registry.your_domain/myproject/alpine:3.20 ``` ## Paso 7: Crear una cuenta robot para CI No uses cuentas personales en los pipelines. Harbor ofrece **cuentas robot** con permisos acotados a un proyecto: 1. En **Projects > myproject > Robot Accounts**, pulsa **New Robot Account**. 2. Escribe `ci` como nombre, elige una caducidad y marca los permisos de **Repository** **Push** y **Pull**. 3. Pulsa **Add** y copia el secreto: solo se muestra una vez. El nombre completo de la cuenta tiene el formato `robot$myproject+ci`. Como contiene `$`, escríbelo entre comillas simples para que el shell no lo interprete. En CI, guarda el secreto en una variable protegida y úsalo así: ```bash echo "$HARBOR_ROBOT_SECRET" | docker login registry.your_domain -u 'robot$myproject+ci' --password-stdin ``` ## Paso 8: Renovar el certificado automáticamente Certbot instala un temporizador que intenta renovar los certificados dos veces al día. En este montaje hay dos detalles: el modo `standalone` necesita el puerto 80, que ahora ocupa Harbor, y Harbor copia el certificado a su propia configuración al ejecutar `prepare`, así que tras renovarlo hay que regenerarla. Resuélvelo con scripts de hook, que Certbot solo ejecuta cuando realmente va a renovar. Crea el hook previo, que detiene Harbor: ```bash sudo nano /etc/letsencrypt/renewal-hooks/pre/harbor-stop.sh ``` ```bash #!/usr/bin/env bash set -euo pipefail cd /opt/harbor docker compose down ``` Y el hook posterior, que regenera la configuración con el certificado nuevo y vuelve a arrancar Harbor: ```bash sudo nano /etc/letsencrypt/renewal-hooks/post/harbor-start.sh ``` ```bash #!/usr/bin/env bash set -euo pipefail cd /opt/harbor ./prepare docker compose up -d ``` Hazlos ejecutables y prueba la renovación en seco: ```bash sudo chmod +x /etc/letsencrypt/renewal-hooks/pre/harbor-stop.sh /etc/letsencrypt/renewal-hooks/post/harbor-start.sh sudo certbot renew --dry-run ``` ```output Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/registry.your_domain/fullchain.pem (success) ``` Durante la prueba Harbor se detiene y arranca de nuevo; comprueba después con `sudo docker compose ps` en `/opt/harbor` que todos los servicios han vuelto. La renovación real provoca una parada de uno o dos minutos cada 60 días aproximadamente. ## Mantenimiento Borrar etiquetas en la interfaz no libera espacio en disco: las capas quedan huérfanas hasta que se ejecuta la recolección de basura. Prográmala en **Administration > Clean Up > Garbage Collection**, por ejemplo semanalmente. Para que no se acumulen etiquetas antiguas, define en cada proyecto una **Tag Retention** (por ejemplo, conservar las 10 etiquetas más recientes por repositorio). Para hacer una copia de seguridad coherente, detén Harbor y copia el directorio de datos junto con la configuración: ```bash cd /opt/harbor sudo docker compose down sudo tar -czf "/var/backups/harbor-$(date +%F).tar.gz" /data /opt/harbor/harbor.yml sudo docker compose up -d ``` Los logs de todos los componentes están en `/var/log/harbor/`. Para un servicio concreto, usa `sudo docker compose logs core` (o `registry`, `nginx`, `trivy-adapter`) desde `/opt/harbor`. ## Solución de problemas **`certbot` falla con `Could not bind TCP port 80`**: algo escucha ya en el puerto 80, normalmente Harbor o un servidor web. Comprueba con `sudo ss -ltnp 'sport = :80'` y detén el servicio que lo ocupe. **`docker login` devuelve `x509: certificate signed by unknown authority` o un error de nombre**: el `hostname` de `harbor.yml` no coincide con el nombre del certificado, o estás usando la IP en lugar del dominio. **`docker push` falla con `unauthorized: unauthorized to access repository`**: el usuario no es miembro del proyecto con rol **Developer** o superior, o la ruta de la imagen no incluye el nombre del proyecto. **Después de cambiar `harbor.yml` no se aplica nada**: los cambios solo se aplican al regenerar la configuración. Ejecuta `sudo docker compose down`, `sudo ./prepare` y `sudo docker compose up -d` desde `/opt/harbor`. ## Conclusión Tienes un registro Harbor privado en Ubuntu 24.04, servido con HTTPS y renovación automática del certificado, que analiza cada imagen con Trivy al subirla y ofrece cuentas robot para tus pipelines. Como siguientes pasos, puedes hacer que tu pipeline de Jenkins o GitLab CI publique las imágenes en Harbor, configurar la replicación con otro registro en **Administration > Registries** y **Replications**, o usar Harbor como caché de Docker Hub creando un proyecto de tipo **Proxy Cache**.