Docker Hub's anonymous pull limits and per-seat pricing on private repos have a way of showing up at the worst time — mid-deploy, mid-incident, mid-demo. Self-hosting a Docker registry on a VPS sidesteps both problems: no rate limiting on your own infrastructure, no per-user tax on private images, and full control over retention and access. This is a sizing and setup guide for a self-hosted docker registry vps running Docker Distribution or Harbor, matched to actual image storage volume and CI pull frequency rather than guesswork.
Why Bother Self-Hosting a Registry
Docker Hub throttles anonymous and free-tier pulls per six-hour window, and that ceiling gets hit fast once a CI pipeline is pulling base images on every build. Private repositories on Hub, GHCR, or most managed registries also bill per seat or per organization member, which scales badly once more than a couple of people or service accounts need pull access. A private docker registry hosting setup on a VPS you control has neither limit — it's your storage, your bandwidth, your uptime to manage.
The tradeoff is operational: you're now responsible for TLS, auth, garbage collection, and backups. For a small-to-mid engineering team or an agency running client CI pipelines, that tradeoff is usually worth it within the first few months, especially once Hub's rate limits start blocking deploys.
Distribution vs Harbor: Picking Your Registry Software
Two realistic options for a self-hosted registry:
- Docker Distribution (registry:2) — the reference implementation, a single Go binary in a container. Minimal footprint, no UI beyond the API, config via one YAML file. Good fit for a single team or a CI-only registry with no need for RBAC.
- Harbor — a CNCF project layering a web UI, project-based RBAC, vulnerability scanning (Trivy), image signing, and replication on top of Distribution. Heavier — it's a docker-compose stack of a dozen or so containers (core, portal, registry, database, Redis, job service) — but worth it once you have multiple teams or need audit trails on who pushed what.
If you're not sure, start with plain Distribution behind nginx for TLS termination. It's a smaller thing to operate and you can migrate image data into Harbor later if RBAC and scanning become a requirement.
Sizing the VPS by Storage and Pull Volume
Registry sizing comes down to two numbers: how much image data you're storing (layers add up fast with multiple tags and language runtimes baked in) and how many pulls per hour your CI pipelines generate. Root access on the box supports installing Docker or Harbor directly with no managed-platform layer in the way, which also means no forced feature limits on storage backends or garbage collection schedules.
| Use case | Typical registry footprint | Fit |
|---|---|---|
| Solo dev / small team, few repos, nightly builds | Under 40GB images, low pull volume | VPS I (2GB/1vCPU/40GB) |
| Small team CI, several services, tagged releases kept | 40-80GB, moderate pull bursts | VPS II (4GB/2vCPU/80GB) |
| Multi-repo org, Harbor with scanning + Redis + Postgres | 80-120GB, steady daytime pulls | VPS III/IV (8GB/2vCPU/120GB) |
| Agency or platform team, many client pipelines | 120-200GB, frequent concurrent pulls | VPS V (16GB/4vCPU/200GB) |
| Registry as shared infra across several products | 200-400GB, heavy concurrent CI load | VPS VI (32GB/6vCPU/400GB) |
Full specs and current pricing for every tier are on the VPS hosting page. If your image storage is already tracking past 400GB or you need dedicated disk I/O isolated from other tenants, that's the point to look at dedicated hardware instead.
Docker Registry VPS Setup Walkthrough
For a Distribution-based setup, the shape of it looks like this:
- Provision the VPS, point a subdomain (e.g.
registry.yourdomain.com) at its IPv4/IPv6, and issue a TLS cert (Let's Encrypt via certbot or acme.sh). - Run
registry:2as a container with a bind-mounted volume for/var/lib/registry— this is your image layer storage, so it should sit on the largest disk you provisioned for. - Put nginx or Caddy in front for TLS termination and basic auth (htpasswd) or forward auth to your existing identity provider.
- Set a garbage collection cron (
registry garbage-collect) to reclaim space from untagged/deleted layers — this is the step most self-hosted registries skip and then run out of disk.
For Harbor, the installer script generates a docker-compose.yml from harbor.yml — set the hostname, TLS cert paths, and storage paths there, then install.sh brings up the full stack. Harbor's own Postgres and Redis containers add meaningful RAM overhead versus plain Distribution, which is why Harbor deployments generally want at least the 8GB tier.
Bandwidth and CI Pipeline Fit
A registry that throttles pulls during a deploy defeats the point of self-hosting one. 1 Gbps unmetered symmetric bandwidth on every VPS tier means CI runners pulling images in parallel don't hit a bandwidth ceiling the way they might on a shared or capped connection — useful once you have several pipelines pulling the same base images concurrently at build start.
Hourly billing to the second is a good match for registries that only need to run during a pipeline's active hours — for example, a registry spun up for a burst of nightly builds or a temporary CI environment, rather than paying for a 24/7 instance you don't need. Combined with a median deploy time of 47 seconds, that makes standing up a throwaway or scheduled registry instance for CI workloads practical rather than theoretical, without committing to always-on infrastructure for something that only runs a few hours a day.
Security and Operational Notes
A registry holding proprietary images is a target worth locking down properly:
- Never expose the registry API without TLS and auth — an open registry:2 on port 5000 is a common misconfiguration scanners actively look for.
- Restrict push access separately from pull access where possible (Harbor's RBAC handles this natively; Distribution needs a proxy-layer auth service or token server for anything beyond basic auth).
- Back up the image storage volume and any registry metadata/database on a schedule — losing the registry means rebuilding every image from source, which is rarely fast.
- Every VPS tier ships with free 1 Tbps DDoS protection at L3/4/7, which covers the registry endpoint itself against the flood traffic that occasionally lands on exposed Docker APIs, without needing a separate mitigation service.
How Noded Can Help
We run our own AS60982 network end to end, which is part of why we can offer 1 Gbps unmetered symmetric bandwidth and free DDoS protection on every VPS tier without it being a sales add-on. Root SSH access and 41 OS templates mean you install Distribution or Harbor exactly the way you'd run it on bare metal, and hourly billing to the second means a CI-only registry instance doesn't cost you for the hours it sits idle. If your image storage is already past what a single VPS comfortably holds, our team can walk through moving the registry to a dedicated box with dedicated disk I/O instead. Either way, start by sizing against the table above and provision from our VPS hosting page.
FAQ
Is a self-hosted Docker registry actually cheaper than Docker Hub?
For teams with more than a handful of users needing private repo access, yes — Hub's per-seat pricing scales linearly with headcount while a self-hosted registry's cost is tied to VPS size, which scales with storage and pull volume instead of user count.
Do I need Harbor, or is plain Docker Distribution enough?
Plain Distribution is enough for a single team or a CI-only registry with no need for role-based access control. Reach for Harbor once you need per-project permissions, vulnerability scanning, or an audit trail of who pushed what.
How much VPS storage does a Docker registry actually need?
It depends on image count, tag retention policy, and layer reuse — a handful of services with a few kept tags each can fit well under 40GB, while an org keeping many historical releases across multiple services can climb past 200GB. Run garbage collection regularly to keep storage from growing unbounded.
Will CI pulls get throttled on a self-hosted registry VPS?
Not by bandwidth caps — every VPS tier includes 1 Gbps unmetered symmetric bandwidth, so concurrent pulls from CI runners aren't hitting a data cap or a Docker Hub-style rate limit.
Can I run the registry only during CI hours to save cost?
Yes — since billing is hourly to the second, spinning up a registry instance for a scheduled build window and stopping it afterward is a realistic way to avoid paying for idle time, particularly for infrequent or scheduled pipelines.