Migrate artifacts from JFrog Artifactory, Nexus, or other registries to Harness Artifact Registry using a YAML configuration file. Supports bulk migration with concurrent transfers and dry-run mode.
Usage
hc registry migrate [flags]
Options
--config
string
default:"config.yaml"
required
Path to the migration configuration file (YAML format)
Base URL for the package registry API (overrides config file)
Number of concurrent migration operations (overrides config file)
Allow overwriting existing artifacts in destination
Run in dry-run mode (no uploads, generates file list and directory structure)
Configuration File
Create a YAML configuration file to define the migration:
version: 1.0.0
concurrency: 5
overwrite: false
source:
endpoint: https://source-registry.example.com
type: JFROG # Supported: JFROG, NEXUS
credentials:
username: source_user
password: source_password
insecure: false
destination:
endpoint: https://pkg.harness.io
type: HAR
credentials:
username: harness_user
password: harness_api_key
mappings:
- artifactType: DOCKER
sourceRegistry: docker-repo
destinationRegistry: harness-docker-repo
- artifactType: MAVEN
sourceRegistry: maven-releases
destinationRegistry: harness-maven
- artifactType: NPM
sourceRegistry: npm-local
destinationRegistry: harness-npm
Configuration Structure
Top-Level Fields
Configuration version (currently 1.0.0)
Number of parallel transfers (recommended: 3-10)
Whether to overwrite existing artifacts
Dry-run mode for testing without uploads
Source Registry Configuration
Source registry URL (e.g., https://artifactory.example.com)
Source registry type: JFROG or NEXUS
source.credentials.username
Username for source registry authentication
source.credentials.password
Password or API token for source registry
Skip TLS certificate verification (not recommended)
Destination Registry Configuration
Harness package registry URL (e.g., https://pkg.harness.io)
Must be HAR (Harness Artifact Registry)
destination.credentials.username
Harness username or service account
destination.credentials.password
Harness API key or token
Registry Mappings
Artifact type: DOCKER, MAVEN, NPM, HELM, HELM_LEGACY, PYTHON, NUGET, GO, GENERIC, CONDA, COMPOSER, DART
mappings[].sourceRegistry
Source registry repository name
mappings[].destinationRegistry
Destination Harness registry identifier
mappings[].sourcePackageHostname
Custom hostname for package source (optional)
mappings[].includePatterns
Patterns to include (not yet implemented)
mappings[].excludePatterns
Patterns to exclude (not yet implemented)
Examples
Basic Migration
Migrate using a configuration file:
hc registry migrate -c config.yaml
Dry Run
Test migration without uploading:
hc registry migrate -c config.yaml --dry-run
This generates:
- File list (all files to be migrated)
- Directory structure (organized by package/version)
Use multiple concurrent transfers:
hc registry migrate -c config.yaml --concurrency 10
Overwrite Existing Artifacts
hc registry migrate -c config.yaml --overwrite
Using --overwrite will replace existing artifacts in the destination registry.
Override Package URL
hc registry migrate -c config.yaml --pkg-url https://custom-pkg.harness.io
Migration Configuration Examples
Migrate from JFrog Artifactory
version: 1.0.0
concurrency: 5
source:
endpoint: https://artifactory.company.com
type: JFROG
credentials:
username: jfrog_user
password: ${JFROG_API_KEY}
destination:
endpoint: https://pkg.harness.io
type: HAR
credentials:
username: harness_user
password: ${HARNESS_API_KEY}
mappings:
- artifactType: DOCKER
sourceRegistry: docker-local
destinationRegistry: company-docker
Migrate from Nexus
version: 1.0.0
concurrency: 5
source:
endpoint: https://nexus.company.com
type: NEXUS
credentials:
username: nexus_user
password: ${NEXUS_PASSWORD}
insecure: false
destination:
endpoint: https://pkg.harness.io
type: HAR
credentials:
username: harness_user
password: ${HARNESS_API_KEY}
mappings:
- artifactType: DOCKER
sourceRegistry: docker-hosted
destinationRegistry: company-docker
- artifactType: NPM
sourceRegistry: npm-hosted
destinationRegistry: company-npm
- artifactType: PYTHON
sourceRegistry: pypi-hosted
destinationRegistry: company-pypi
Multi-Type Migration
Migrate multiple artifact types in one operation:
version: 1.0.0
concurrency: 10
overwrite: false
source:
endpoint: https://artifactory.company.com
type: JFROG
credentials:
username: ${SOURCE_USER}
password: ${SOURCE_TOKEN}
destination:
endpoint: https://pkg.harness.io
type: HAR
credentials:
username: ${HARNESS_USER}
password: ${HARNESS_TOKEN}
mappings:
- artifactType: DOCKER
sourceRegistry: docker-local
destinationRegistry: prod-docker
- artifactType: HELM
sourceRegistry: helm-local
destinationRegistry: prod-helm
- artifactType: MAVEN
sourceRegistry: maven-releases
destinationRegistry: prod-maven
- artifactType: NPM
sourceRegistry: npm-local
destinationRegistry: prod-npm
- artifactType: PYTHON
sourceRegistry: pypi-local
destinationRegistry: prod-pypi
- artifactType: NUGET
sourceRegistry: nuget-local
destinationRegistry: prod-nuget
Environment Variables
Use environment variables for sensitive credentials:
version: 1.0.0
concurrency: 5
source:
endpoint: ${SOURCE_ENDPOINT}
type: ${SOURCE_TYPE}
credentials:
username: ${SOURCE_USERNAME}
password: ${SOURCE_PASSWORD}
destination:
endpoint: ${DEST_ENDPOINT}
type: HAR
credentials:
username: ${HARNESS_USERNAME}
password: ${HARNESS_API_KEY}
mappings:
- artifactType: DOCKER
sourceRegistry: ${SOURCE_DOCKER_REPO}
destinationRegistry: ${DEST_DOCKER_REPO}
Then export the variables:
export SOURCE_ENDPOINT="https://artifactory.company.com"
export SOURCE_TYPE="JFROG"
export SOURCE_USERNAME="jfrog_user"
export SOURCE_PASSWORD="jfrog_token"
export HARNESS_USERNAME="harness_user"
export HARNESS_API_KEY="harness_token"
export SOURCE_DOCKER_REPO="docker-local"
export DEST_DOCKER_REPO="company-docker"
hc registry migrate -c config.yaml
Supported Artifact Types
The migration tool supports:
- DOCKER - Docker container images
- HELM - Helm charts (OCI format)
- HELM_LEGACY - Legacy Helm chart repositories
- MAVEN - Java/Maven artifacts
- NPM - Node.js packages
- NUGET - .NET packages
- PYTHON - Python packages (PyPI)
- GO - Go modules
- GENERIC - Generic file artifacts
- CONDA - Conda packages
- COMPOSER - PHP Composer packages
- DART - Dart/Flutter packages
Concurrency Tuning
Optimal concurrency depends on:
- Network bandwidth
- Source registry limits
- Number of artifacts
- Average artifact size
Recommended concurrency values:
- Small artifacts (< 10 MB): 8-15
- Medium artifacts (10-100 MB): 5-10
- Large artifacts (> 100 MB): 3-5
# Small NPM packages
hc registry migrate -c config.yaml --concurrency 15
# Large Docker images
hc registry migrate -c config.yaml --concurrency 5
Dry Run Output
Dry run generates two files:
- File list (
dry-run-files.json):
[
{
"registry": "docker-local",
"name": "myapp",
"uri": "/docker-local/myapp/1.0.0/manifest.json",
"size": 1234,
"lastModified": "2024-01-15T10:30:00Z"
}
]
- Directory structure (
dry-run-structure.json):
{
"docker-local": {
"packages": {
"myapp": {
"versions": {
"1.0.0": {
"files": [
{
"name": "manifest.json",
"size": 1234
}
]
}
}
}
}
}
}
Graceful Shutdown
The migration can be stopped gracefully:
# Press Ctrl+C to stop
^C
Received interrupt signal, shutting down gracefully...
Progress is saved, and you can resume by running the command again.
Migration Progress
During migration, you’ll see:
$ hc registry migrate -c config.yaml
Starting migration...
Processing mapping 1/3: DOCKER docker-local -> company-docker
Migrating image: myapp:1.0.0 [1/45] (2.3 MB)
Migrating image: myapp:1.1.0 [2/45] (2.4 MB)
...
Completed mapping 1/3
Processing mapping 2/3: NPM npm-local -> company-npm
...
Migration completed successfully
Error Handling
Common errors and solutions:
Invalid Credentials
Failed to authenticate with source registry: invalid credentials
Solution: Verify username and password/token in config file.
Registry Not Found
Failed to find registry 'docker-local' in source
Solution: Check source registry name. List available repositories in source.
Network Timeout
Failed to download artifact: connection timeout
Solution: Reduce concurrency or check network connectivity.
Destination Registry Missing
Destination registry 'company-docker' not found
Solution: Create the destination registry first:
hc registry create company-docker --package-type DOCKER
Best Practices
- Test with dry run: Always run
--dry-run first
- Start small: Begin with one mapping, then scale up
- Use environment variables: Keep credentials out of config files
- Monitor progress: Watch for errors and adjust concurrency
- Verify after migration: Check artifact counts and sizes
- Plan downtime: Schedule migration during low-usage periods
Post-Migration Verification
After migration, verify the results:
# Check destination registry
hc registry get company-docker
# Compare artifact counts
# Source: Check in JFrog/Nexus UI
# Destination:
hc registry get company-docker --format json | jq '.data.registries[0].registrySize'