Deploy Harbor Registry
Deploy a private Docker container registry using Harbor through PodWarden
Harbor is an open-source container registry with vulnerability scanning, access control, and image replication. PodWarden can deploy and manage Harbor as a workload on your K8s cluster.
Deploy from Hub
Harbor is available in the PodWarden Hub catalog. Import and deploy it like any other application:
- Import the Harbor template from Hub
- Choose a target cluster with sufficient resources (Harbor needs ~2GB RAM minimum)
- Create a deployment and fill in required env values (admin password, secret key)
- Deploy and verify pods are running
Post-Deploy Configuration
PKCS#1 Key Conversion
Harbor's token authentication uses RSA keys for signing JWTs. If you see this error in the core service logs:
unable to get PrivateKey from PEM type: PRIVATE KEYThe private key is in PKCS#8 format but Harbor requires PKCS#1. Convert it:
run_in_pod(deployment_id="...", command="openssl rsa -in /etc/core/private_key.pem -out /tmp/key.pem -traditional", container="core")Then update the core ConfigMap with the converted key and regenerate root.crt. Restart core and registry pods.
Ingress for Docker Push/Pull
Harbor requires two ingress routes to function correctly with docker push and docker pull:
-
Default route (
/) — points to Harbor's nginx service (port 8080). Handles the web UI, API, and token service. -
Registry route (
/v2) — points directly to the registry service (port 5000) with higher priority. This is necessary because Harbor's internal proxy chain can strip theAuthorizationheader before it reaches the registry backend.
Without the direct /v2 route, docker login may succeed but docker push will fail with unauthorized.
If you're using PodWarden's ingress system, create both rules pointing to the appropriate services. If using Traefik directly, set a higher priority on the /v2 route.
Robot Accounts for CI
For CI/CD pipelines, create a robot account instead of using the admin credentials:
- Log in to Harbor web UI
- Navigate to your project → Robot Accounts
- Create a robot account with Push and Pull permissions
- Use the robot credentials in your CI pipeline
Robot account usernames contain a $ character (e.g., robot$ci-push). Make sure your CI system does not perform shell variable expansion on the username — most CI systems have a "raw" or "literal" option for variables.
Auth Mode
Harbor supports two authentication modes:
- db_auth — local database authentication (default). Users are managed in Harbor directly.
- oidc — delegates authentication to an OIDC provider (Keycloak, Authentik, etc.)
Switching to OIDC mode disables local admin authentication entirely. Make sure your OIDC provider is working before switching. If you get locked out, you can revert via direct database access: UPDATE properties SET v = 'db_auth' WHERE k = 'auth_mode'; in Harbor's PostgreSQL database.
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
unable to get PrivateKey from PEM type | PKCS#8 key format | Convert to PKCS#1 with openssl rsa ... -traditional |
docker push unauthorized (login works) | /v2 routed through core proxy | Add direct Ingress route to registry:5000 for /v2 |
| Robot account auth fails in CI | $ in username gets shell-expanded | Set CI variable to raw/literal mode |
| Admin can't log in after OIDC setup | OIDC blocks local auth | Reset auth_mode to db_auth in DB |
| Pods stuck in CrashLoopBackOff | Missing or wrong secrets/config | Check core logs, verify all ConfigMaps are populated |