Container images contain your application code, configuration, and dependencies. Pushing images to public or cloud-hosted registries (Docker Hub, AWS ECR, GCR) exposes your software to the registry operator and potentially to other parties. Even private registries on cloud providers can be accessed by cloud staff or through data requests. A self-hosted container registry running as a Tor hidden service provides maximum privacy: images are stored on your own infrastructure, the registry is not accessible without the .onion address, and image pulls by CI/CD systems happen without exposing the registry server's IP. This guide covers deploying the Docker Registry (distribution) and Harbor as Tor hidden services.
Need this done for your project?
We implement, you ship. Async, documented, done in days.
Cloud container registries have several privacy concerns beyond just access control. Registry operators can inspect image layers, audit pull patterns, and are subject to law enforcement requests for registry contents. Container images may contain proprietary code, API keys left in layers (a common security mistake), or sensitive configuration. Even with strong access controls on a cloud registry, the operator retains access to the stored data. A self-hosted .onion registry eliminates all of these: no third party has access to your images, the registry is not discoverable by internet scanners, and pull patterns (which application is pulling which image version) are not visible to any external party.
Deploying Docker Distribution (Registry v2) on .onion
Docker Registry (the official CNCF distribution project) is a lightweight Go binary. Deploy via Docker: docker run -d --name registry --restart always -p 127.0.0.1:5000:5000 -v /var/lib/registry:/var/lib/registry registry:2. The registry listens on localhost:5000. Configure Tor: HiddenServiceDir /var/lib/tor/container-registry/ and HiddenServicePort 5000 127.0.0.1:5000. Add authentication: generate htpasswd credentials and configure the registry to require authentication. Configure TLS for the registry (required by Docker daemon when pushing to non-localhost registries): generate a self-signed certificate. On client machines (developer laptops, CI servers): configure the Docker daemon to trust your self-signed CA, configure HTTP_PROXY=socks5://127.0.0.1:9050 so Docker pulls route through Tor. Push images: docker tag myimage youraddress.onion:5000/myimage && docker push youraddress.onion:5000/myimage.
Harbor as a Feature-Rich .onion Registry
Harbor is the CNCF-graduated enterprise container registry with vulnerability scanning, RBAC, and replication. It runs as a Docker Compose stack. Configure the harbor.yml: hostname: youraddress.onion, http.port: 80 (Harbor runs its own Nginx). Add the Nginx listening configuration to expose on 127.0.0.1:80 only. Configure Tor to point to 127.0.0.1:80. Harbor includes Trivy for vulnerability scanning of images - this requires internet access from the Harbor server to update vulnerability databases. Configure Trivy to use Tor for database updates: set HTTP_PROXY=socks5h://127.0.0.1:9050 in the Trivy configuration. Harbor's web interface is accessible via Tor Browser at the .onion URL, providing a full GUI for managing images, users, and projects.
CI/CD Integration with .onion Container Registry
CI/CD pipelines that build and push container images need Tor access to reach the .onion registry. For self-hosted CI (GitLab CI self-hosted, Drone CI, Woodpecker CI) on a VPS: install Tor on the CI server, configure Docker daemon with SOCKS proxy, and run docker build + push commands as normal. For GitHub Actions with self-hosted runners: the self-hosted runner machine needs Tor and Docker configured as above. The build workflow: (1) build image: docker build -t youraddress.onion:5000/app:${VERSION} ., (2) push image: docker push youraddress.onion:5000/app:${VERSION}, (3) deployment: docker pull on the deployment server via Tor. Each docker push/pull over Tor adds 30-120 seconds depending on image size and Tor circuit bandwidth.
Image Scanning and Security Policies
Container security scanning should be integrated into the registry workflow. Trivy (standalone) can scan images via torsocks if vulnerability database updates are fetched over Tor. Grype (Anchore's scanner) also supports proxy-based vulnerability database fetching. Configure scanning as a mandatory step before images are promoted to production tags: (1) image pushed to staging tag, (2) scanner runs and reports vulnerabilities, (3) if no critical vulnerabilities: automated promotion to production tag, (4) if critical vulnerabilities found: block promotion, notify developers. Harbor includes integrated scanning via Trivy with policy enforcement. For the Docker Registry v2 without Harbor: implement scanning in the CI/CD pipeline before the push step.