Configure Harbor replication
This guide explains how to configure and manage replication with Numspot Container Registry instances based on Harbor.
Overview
Harbor replication allows you to synchronize container images and OCI artifacts between registries. On the Numspot platform, replication supports two main use cases:
Use cases
1. Migration to Numspot (inbound replication)
Pull images from your existing container registry to a Numspot Container Registry instance. This is ideal for:
- Cloud migration: move workloads to the Numspot sovereign cloud
- Consolidation: centralize container images from several registries
- Backup: create a redundant copy of critical images on Numspot
2. Reversibility - Leaving Numspot (outbound replication)
Push images from your Numspot Container Registry to an external registry. This ensures:
- Portability: meet regulatory cloud reversibility requirements
- Multi-cloud strategy: distribute images across several providers
- Disaster recovery: keep off-platform backups of your images
Replication modes
| Mode | Description | Use case |
|---|---|---|
| Pull-based | Pull artifacts from a remote registry to Numspot | Migrate to Numspot, mirror external registries |
| Push-based | Push artifacts from Numspot to a remote registry | Reversibility, multi-cloud distribution |
Supported registries
The Numspot Container Registry can replicate to/from:
- Docker Hub
- AWS Elastic Container Registry (ECR)
- Azure Container Registry (ACR)
- Google Container Registry (GCR) / Artifact Registry
- Quay
- GitLab Registry
- JFrog Artifactory
- Ali Cloud Container Registry
- Huawei SWR
- Other Harbor instances (including other Numspot registries)
Prerequisites
For the Numspot Container Registry
Before configuring replication, ensure that:
- The Numspot Registry instance is created and running
- Network connectivity between the source and destination registries
- Admin credentials for the Numspot registry instance
- Space ID and Registry ID of your Numspot instance
Required permissions
- Source registry: read access (pull images)
- Destination registry: write access (push images)
- Numspot IAM: permission to manage registry instances
Part 1: Managing Numspot Container Registry instances
1.1 Create a Container Registry instance
Before configuring replication, create a registry instance via the Numspot API:
curl -X POST "https://api.cloudgouv-eu-west-1.numspot.com/registry/spaces/{spaceId}/registries" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "my-production-registry",
"version": "2.14",
"visibility": "EXTERNAL"
}'
Parameters:
| Field | Type | Description | Values |
|---|---|---|---|
name | string | Registry name (DNS-compatible) | my-registry, prod-registry |
version | string | Harbor version | 2.13, 2.14 |
visibility | string | Network accessibility | EXTERNAL (public endpoint), INTERNAL (requires VPN) |
Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "my-production-registry",
"version": "2.14",
"visibility": "EXTERNAL",
"status": {
"state": "CREATING",
"message": "Registry is being provisioned"
},
"host": "https://registry-123e4567-e89b-12d3-a456-426614174000.hcp.cloudgouv-eu-west-1.numspot.com"
}
1.2 Retrieve admin credentials
Obtain the admin password for your registry:
curl -X GET "https://api.cloudgouv-eu-west-1.numspot.com/registry/spaces/{spaceId}/registries/{registryId}/password" \
-H "Authorization: Bearer {token}"
Response:
{
"password": "generated-secure-password"
}
Default username: admin
1.3 List Registry instances
List all registries in your space:
curl -X GET "https://api.cloudgouv-eu-west-1.numspot.com/registry/spaces/{spaceId}/registries" \
-H "Authorization: Bearer {token}"
1.4 Get Registry details
Retrieve the information of a specific registry:
curl -X GET "https://api.cloudgouv-eu-west-1.numspot.com/registry/spaces/{spaceId}/registries/{registryId}" \
-H "Authorization: Bearer {token}"
Registry states:
| State | Description |
|---|---|
CREATING | The registry is being provisioned |
RUNNING | The registry is operational |
PENDING | The registry is being configured |
UPGRADING | A version upgrade is in progress |
REPAIRING | Automatic repair is in progress |
FAILED | Provisioning failed |
DELETING | The registry is being deleted |
Part 2: Scenario 1 - Migrating images to Numspot
Use Pull-based replication to migrate images from an external registry to Numspot.
2.1 Architecture overview
External Registry Numspot Container Registry
(Docker Hub/AWS ECR/...) (Harbor Instance)
│ │
└──── Pull Replication ────→│
(Destination)
2.2 Step-by-step configuration
Step 1: Access the Harbor interface
- Retrieve your registry host from the API response or the Numspot console
- Go to:
https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com - Log in with:
- Username:
admin - Password: use the password obtained via the API (section 1.2)
- Username:
Step 2: Create a replication endpoint (external registry)
-
Go to Administration → Registries
-
Click + New Endpoint
-
Configure the external registry:
Field Value Provider Docker Hub,AWS ECR, etc.Name source-docker-hubEndpoint URL https://registry-1.docker.io(Docker Hub)Access ID Your Docker Hub username Access Secret Your Docker Hub password/token Verify Remote Cert Enabled -
Click Test Connection
-
Click OK to save
Step 3: Create a Pull replication rule
-
Go to Administration → Replications
-
Click New Replication Rule
-
Configure:
Basic parameters:
Field Value Name migrate-docker-hub-imagesDescription Pull critical images from Docker Hub to NumspotReplication Mode Pull-basedSource (external registry):
Field Value Source Registry source-docker-hubFilters:
Field Value Name library/nginx,library/redisTag latest,alpineResource AllTrigger mode:
- Manual: one-off migration
- Scheduled: periodic synchronization (e.g.
0 2 * * *daily at 2 a.m.)
Advanced:
Field Value Override (overwrite existing images) Bandwidth -1(unlimited) or a limit according to your needs -
Click Save
Step 4: Run the replication
- Select the replication rule
- Click Replicate
- Monitor progress in the Executions tab
Step 5: Verify the migration
Once replication is complete:
## List the repositories in the Numspot registry
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/1/repositories" \
-u "admin:{password}"
## Pull an image from Numspot
docker pull registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/library/nginx:latest
2.3 Example: Migrate from AWS ECR
## Create an endpoint for AWS ECR
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/registries" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "source-aws-ecr",
"type": "aws-ecr",
"url": "https://123456789.dkr.ecr.us-east-1.amazonaws.com",
"credential": {
"type": "basic",
"access_key": "AKIAIOSFODNN7EXAMPLE",
"access_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
},
"insecure": false
}'
## Create a pull replication rule
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/policies" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "migrate-from-aws-ecr",
"description": "Migrate all ECR images to Numspot",
"src_registry": {"id": 1},
"dest_namespace": "aws-migration",
"trigger": {"type": "manual"},
"filters": [
{"type": "name", "value": "**"}
],
"enabled": true,
"override": true
}'
## Trigger the replication
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{"policy_id": 1}'
Part 3: Scenario 2 - Reversibility (Leaving Numspot)
Use Push-based replication to migrate images from Numspot to an external registry.
3.1 Architecture overview
Numspot Container Registry External Registry
(Harbor Instance) (AWS ECR/ACR/Other Harbor/...)
│ │
└──── Push Replication ───────→│
(Source) (Destination)
3.2 Step-by-step configuration
Step 1: Create a destination registry endpoint
-
Access your Numspot Harbor interface
-
Go to Administration → Registries
-
Click + New Endpoint
-
Configure the destination registry:
Field Value Provider Harbor,AWS ECR, etc.Name destination-external-registryEndpoint URL https://your-registry.example.comAccess ID Username or access key Access Secret Password or secret key Verify Remote Cert Enabled -
Click Test Connection
-
Click OK
Step 2: Create a Push replication rule
-
Go to Administration → Replications
-
Click New Replication Rule
-
Configure:
Basic parameters:
Field Value Name reversibility-full-exportDescription Push all images to external registry for reversibilityReplication Mode Push-basedDestination (external registry):
Field Value Destination Registry destination-external-registryDestination Namespace numspot-backup(or leave empty to preserve the structure)Filters:
Field Value Name **(all repositories)Tag *(all tags)Resource AllTrigger mode:
- Manual: one-off export for reversibility
- Event Based: continuous synchronization (with deletion option)
Destination flattening:
Select according to your target registry:
- No Flattening: preserve the full namespace hierarchy
- Flatten 1-3 Levels: simplify the path structure
Advanced:
Field Value Override (overwrite existing images) Delete remote resources when locally deleted (for Event Based) -
Click Save
Step 3: Run the full export
- Select the replication rule
- Click Replicate
- Monitor progress:
- Check the Executions tab
- Click the execution ID for the detailed task list
- Track the replicated artifacts, the speed and the duration
Step 4: Verify the export
Once replication is complete, verify the images in the destination registry:
## List the repositories in the destination
curl -X GET "https://your-registry.example.com/api/v2.0/projects/1/repositories" \
-u "username:password"
## Pull an image from the destination
docker pull your-registry.example.com/numspot-backup/myapp:v1.0
Step 5: Document the reversibility
Keep documentation of:
- The replication rule configuration
- The execution logs and timestamps
- The verification results
- Any manual post-processing steps
3.3 Example: Push to AWS ECR
## Create an endpoint for AWS ECR (destination)
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/registries" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "destination-aws-ecr",
"type": "aws-ecr",
"url": "https://123456789.dkr.ecr.eu-west-3.amazonaws.com",
"credential": {
"type": "basic",
"access_key": "AKIAIOSFODNN7EXAMPLE",
"access_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}'
## Create a push replication rule
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/policies" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "reversibility-push-to-ecr",
"description": "Full image export to AWS ECR for reversibility compliance",
"dest_registry": {"id": 2},
"dest_namespace": "numspot-export",
"dest_namespace_replace_count": 0,
"trigger": {"type": "manual"},
"filters": [
{"type": "name", "value": "**"}
],
"enabled": true,
"override": true,
"speed": -1
}'
## Run the push replication
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{"policy_id": 2}'
3.4 Checklist for reversibility compliance
For regulatory compliance, ensure that:
- All projects/repositories are included in the replication filters
- All image tags are replicated (no filter exclusions)
- Image signatures (Cosign) are replicated
- The replication execution logs are backed up
- The destination registry is accessible and functional
- Images can be pulled from the destination registry
- Application workloads can use the destination images
- The documentation includes the full replication configuration
Part 4: Registry-specific configuration
Docker Hub
{
"type": "docker-hub",
"url": "https://registry-1.docker.io",
"credential": {
"access_key": "dockerhub-username",
"access_secret": "dockerhub-password-or-token"
}
}
Note: for official images, use the library/ prefix in the filters (e.g. library/nginx).
AWS ECR
{
"type": "aws-ecr",
"url": "https://123456789.dkr.ecr.us-east-1.amazonaws.com",
"credential": {
"access_key": "AKIAIOSFODNN7EXAMPLE",
"access_secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}
Required IAM permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:CreateRepository",
"ecr:SetRepositoryPolicy"
],
"Resource": "*"
}
]
}
Google GCR/Artifact Registry
{
"type": "google-gcr",
"url": "https://gcr.io/my-project",
"credential": {
"access_key": "_json_key",
"access_secret": "{\"type\":\"service_account\",\"project_id\":\"my-project\",...}"
}
}
Note: the namespace must start with the project ID.
Azure Container Registry
{
"type": "azure-acr",
"url": "https://myregistry.azurecr.io",
"credential": {
"access_key": "myregistry",
"access_secret": "registry-password-or-access-key"
}
}
Quay
{
"type": "quay",
"url": "https://quay.io",
"credential": {
"access_key": "json_file",
"access_secret": "{\"oauth2_token\":\"...\",\"account_name\":\"user\",\"docker_cli_password\":\"...\"}"
}
}
Other Harbor instances
{
"type": "harbor",
"url": "https://harbor.example.com",
"credential": {
"access_key": "admin",
"access_secret": "harbor-password"
},
"insecure": false
}
Part 5: Advanced replication scenarios
5.1 Cross-replication between Numspot Registry instances
Replicate between two Numspot Container Registry instances:
Scenario: production registry in EU-West-1 to disaster recovery (DR) registry in EU-West-2
## Source: EU-West-1 Registry (source-registry-id)
## Destination: EU-West-2 Registry (dest-registry-id)
## On the source registry, create an endpoint for the destination
curl -X POST "https://registry-{source-registry-id}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/registries" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "dr-registry-eu-west-2",
"type": "harbor",
"url": "https://registry-{dest-registry-id}.hcp.cloudgouv-eu-west-2.numspot.com",
"credential": {
"access_key": "admin",
"access_secret": "{dest-registry-password}"
}
}'
## Create a push replication rule for the DR
curl -X POST "https://registry-{source-registry-id}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/policies" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "dr-replication-to-eu-west-2",
"dest_registry": {"id": 1},
"trigger": {
"type": "event_based",
"trigger_settings": {
"replicate_deletion": true
}
},
"filters": [{"type": "name", "value": "**"}],
"enabled": true,
"override": true
}'
5.2 Scheduled cross-cloud backup
Create a daily backup to an external cloud provider:
## Create a scheduled replication (runs daily at 2 a.m.)
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/policies" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "daily-backup-to-external",
"description": "Daily cross-cloud backup",
"dest_registry": {"id": 3},
"trigger": {
"type": "scheduled",
"trigger_settings": {
"cron": "0 2 * * *"
}
},
"filters": [
{"type": "name", "value": "production/**"},
{"type": "tag", "value": "v*"}
],
"enabled": true,
"override": true,
"speed": 10240
}'
5.3 Selective migration with filters
Migrate only specific images:
## Migrate only production images with semantic versioning
curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/policies" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"name": "migrate-production-images",
"src_registry": {"id": 1},
"filters": [
{
"type": "name",
"value": "{api,frontend,backend}/**"
},
{
"type": "tag",
"value": "v[0-9]+.[0-9]+.[0-9]+"
},
{
"type": "label",
"value": "production"
}
],
"trigger": {"type": "manual"},
"enabled": true
}'
Part 6: Monitoring and troubleshooting
6.1 Monitor the replication status
Via the Harbor interface
- Go to Administration → Replications
- Click a replication rule
- Check the Executions tab
- Click the execution ID to view the detailed tasks
Via the API
## List the replication executions
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions?policy_id=1" \
-u "admin:{password}"
## Get the details of a specific execution
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions/{execution_id}/tasks" \
-u "admin:{password}"
## Check the status of an execution
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions/{execution_id}" \
-u "admin:{password}" | jq '.status'
6.2 Common issues and solutions
Issue 1: Registry not started
Symptom: unable to access the Harbor interface, or the API returns 503
Solution:
## Check the registry status via the Numspot API
curl -X GET "https://api.cloudgouv-eu-west-1.numspot.com/registry/spaces/{spaceId}/registries/{registryId}" \
-H "Authorization: Bearer {token}"
## Expected state: "RUNNING"
## If "FAILED", check the error message and contact support
Issue 2: Connection timeout to the external registry
Symptom: Test Connection fails with a timeout
Solutions:
- Check that the external registry URL is correct and accessible
- Check whether the external registry requires a VPN/whitelist
- Disable Verify Remote Cert if you use self-signed certificates (not recommended in production)
- Test the connectivity:
curl -vk https://external-registry.example.com/v2/
Issue 3: Authentication failure
Symptom: the replication task fails with 401 Unauthorized
Solutions:
For AWS ECR:
- Use access keys, not an IAM role
- Check that the keys have the required ECR permissions
- Check that the keys are not expired
For GCR:
- Ensure that the service account JSON is complete
- Check that the service account has the
roles/storage.objectAdminrole
For Harbor (Numspot or external):
- Check that the admin password is correct
- Use robot accounts with limited permissions
- Check that the robot account has push/pull permissions on the target projects
Issue 4: Partial replication failure
Symptom: some artifacts succeed, others fail
Solutions:
-
Check the destination storage quota:
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/systeminfo" \-u "admin:{password}" | jq '.storage' -
Check the logs of the failed tasks:
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/replication/executions/{execution_id}/tasks?status=error" \-u "admin:{password}" -
Check the image size limits and the blob upload capabilities
Issue 5: Network bandwidth issues
Symptom: replication is slow or hangs
Solutions:
- Increase the bandwidth limit in the replication rule (or set it to
-1for unlimited) - Reduce the number of concurrent workers if the network is saturated
- Use Copy by Chunk for large images:
# Enable Copy by Chunk in the replication rule# Or set the environment variable in Harbor jobserviceREPLICATION_CHUNK_SIZE=10485760 # 10MB
6.3 Harbor logs
Access the logs of the Harbor components (for internal Numspot debugging):
## jobservice logs (replication tasks)
kubectl logs -n registry-instance-{registryId} deployment/harbor-jobservice -f
## core logs (API requests)
kubectl logs -n registry-instance-{registryId} deployment/harbor-core -f
## registry logs (image push/pull)
kubectl logs -n registry-instance-{registryId} deployment/harbor-registry -f
Accessing the logs requires access to the Kubernetes cluster. Contact Numspot support for assistance.
Part 7: API reference
Numspot Registry API
Base URL
https://api.cloudgouv-eu-west-1.numspot.com
List Registries
GET /registry/spaces/{spaceId}/registries
Authorization: Bearer {token}
Create a Registry
POST /registry/spaces/{spaceId}/registries
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "string",
"version": "2.13" | "2.14",
"visibility": "EXTERNAL" | "INTERNAL"
}
Get a Registry
GET /registry/spaces/{spaceId}/registries/{registryId}
Authorization: Bearer {token}
Get the admin password
GET /registry/spaces/{spaceId}/registries/{registryId}/password
Authorization: Bearer {token}
Delete a Registry
DELETE /registry/spaces/{spaceId}/registries/{registryId}
Authorization: Bearer {token}
Harbor replication API
Base URL
https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com
Create a replication endpoint
POST /api/v2.0/registries
Authorization: Basic {base64(admin:password)}
Content-Type: application/json
{
"name": "string",
"type": "harbor | docker-hub | aws-ecr | azure-acr | google-gcr | quay | ...",
"url": "string",
"credential": {
"type": "basic",
"access_key": "string",
"access_secret": "string"
},
"insecure": false
}
Create a replication policy
POST /api/v2.0/replication/policies
Authorization: Basic {base64(admin:password)}
Content-Type: application/json
{
"name": "string",
"description": "string",
"src_registry": {"id": number},
"dest_registry": {"id": number},
"dest_namespace": "string",
"dest_namespace_replace_count": number,
"trigger": {
"type": "manual | scheduled | event_based",
"trigger_settings": {
"cron": "0 0 * * *",
"replicate_deletion": true
}
},
"filters": [
{"type": "name | tag | label | resource", "value": "string", "decoration": "matches | excludes"}
],
"enabled": true,
"override": false,
"speed": -1
}
Trigger a replication
POST /api/v2.0/replication/executions
Authorization: Basic {base64(admin:password)}
Content-Type: application/json
{
"policy_id": number
}
Get a replication execution
GET /api/v2.0/replication/executions/{executionId}
Authorization: Basic {base64(admin:password)}
Get the replication tasks
GET /api/v2.0/replication/executions/{executionId}/tasks
Authorization: Basic {base64(admin:password)}
Limitations
- Replication between Harbor v1.x and v2.x is not supported
- Harbor does not support the Docker registry manifest schema1 in Quay registries
- Member information is not replicated between Harbor instances
- Deletion operations are not replicated in Manual or Scheduled trigger modes
- For Numspot registries: the version must be
2.13or2.14 - API changes between Harbor versions may cause incompatibilities
- Large images (>5GB) must use Copy by Chunk for greater reliability
Additional resources
- Official Harbor documentation
- Harbor replication guide
- Numspot console
- Numspot OpenAPI specification