Harbor as Container Registry
Date: 2026-03-23 Status: Accepted Context: Choosing where to store container images built by student CI pipelines
Decision
Run a self-hosted Harbor instance on the platform cluster as the container registry for all projects.
Organization
harbor.prod.fontysvenlo.dev/
├── prj2-2026/ # Per-year project, one per cohort
│ ├── group01-backend
│ ├── group01-frontend
│ ├── group02-backend
│ └── ...
├── spohf/ # Research project images
└── platform/ # Platform internal images (docs-site, db-init, etc.)
Rationale
- Full control over retention, access policies, and cleanup. When a project ends, delete the Harbor project and all images are gone — clean lifecycle management.
- Project-based model maps naturally to team isolation. Each year/cohort gets a project; each team gets image repositories within it.
- Simpler integration with ArgoCD Image Updater — Image Updater polls Harbor's API directly with a single set of credentials. No complex token management per-org.
- GHCR access control is messy — GitHub Container Registry's permission model is tied to GitHub orgs/users in ways that make bulk management and cleanup painful. Harbor's project model is simpler and more predictable.
- Data sovereignty — images stay on our own infrastructure, not dependent on GitHub's availability or policy changes.
- Educational value — having a self-hosted registry is part of showing students a realistic production setup.
- Trivy vulnerability scanning as a bonus — images are scanned on push without extra tooling.
Alternatives Considered
GitHub Container Registry (GHCR)
- ✅ No infrastructure to maintain
- ✅ Close to student repositories
- ❌ Access control is complex and poorly documented for education use cases
- ❌ Cleanup across organizations/repos is manual and tedious
- ❌ Dependency on external service availability
- Rejected: Operational friction outweighs convenience
Docker Hub
- ✅ Most well-known registry
- ❌ Rate limits on free tier
- ❌ No project-based organization model
- ❌ Public by default (private repos cost money)
- Rejected: Rate limits and cost model don't fit
Quay (Red Hat)
- ✅ Open-source, feature-rich
- ❌ Extra hosted service to manage or another self-hosted component
- ❌ No significant advantage over Harbor for our use case
- Rejected: No compelling reason to choose over Harbor
Consequences
Positive
- Clean project lifecycle (create project → teams push → delete project when done)
- Image Updater integration is straightforward
- Vulnerability scanning without extra tooling
- Full audit trail of image pushes
Negative
- Another service to host and maintain on the cluster
- Harbor's internal PostgreSQL and Redis add resource consumption
- Harbor upgrades require careful planning (stateful service)
- Admin password currently in plaintext in values file (known TODO)