Migrate from JFrog Artifactory to Pulp: what moves cleanly and what does not
A platform team that runs Maven, npm or Python repositories in JFrog Artifactory and wants them self-hosted should plan a rebuild of repositories and remotes in Pulp, not a copy of the Artifactory data. The work is usually carried out by the internal platform or build engineering team with an implementation partner such as DeployOpen, because the hard part is reproducing access rules, upstream sources and client configuration, not moving bytes. Effort and risk depend less on the volume of artifacts than on how many local, remote and virtual repositories exist and how many CI jobs and developer machines point at them.
The first practical step is an inventory. For each hosted repository, record the package type, who publishes to it and whether anything depends on SNAPSHOT versions. For each remote, record the upstream URL and credentials. Downloads can be scripted with the JFrog CLI command jf rt download, which keeps the repository folder hierarchy and verifies checksums by default, so the files can be loaded into Pulp for each package format. Confirm with JFrog which export options your subscription allows, because the export path differs between SaaS and self-managed deployments.
Maven needs the most scrutiny. The pulp_maven deploy path does not use authentication and does not separate SNAPSHOT and release repositories, so any Maven publishing workflow that relies on Artifactory permission targets must be redesigned, typically with a reverse proxy or identity layer in front of Pulp. npm and Python are closer to a like-for-like move, since pulp_npm accepts npm publish and yarn publish, but the plugin maturity differs: pulp_npm and pulp_maven are still 0.x releases, so the reader should test the exact client versions and the upload flows used in their own pipelines before cutover.
Virtual repositories have no direct equivalent in Pulp, so each client that resolved through a virtual repository needs to be pointed at a distribution or a deliberately chosen source. Confirm the Pulp plugin versions and tech-preview status for every format in scope, run a parallel build against both systems, and keep Artifactory read-only for a fallback period. Container content belongs to the Harbor migration page.
Which Artifactory repository features map to Pulp plugins
This table maps Artifactory local, remote and virtual repositories, package formats, checksums and Maven deploy behavior to Pulp plugins. Each row is marked clean, needs rework or gap, so you can see which repositories move with little change and which need a redesign before cutover. Check plugin maturity in the last column before you commit a format to production.
| Artifactory feature | Pulp equivalent | Status | Plugin maturity and what to check |
|---|---|---|---|
| Local Maven repository | pulp_maven hosted content, published with the Maven Deploy Plugin | Needs rework | pulp_maven is 0.35.0. Deploy uses no authentication and does not separate SNAPSHOT from release, so set access controls outside the deploy path. |
| Remote Maven repository (Maven Central) | pulp_maven remote with pull-through cache | Clean | pulp_maven documents caching Maven Central or another Maven repository. Confirm upstream URLs and credentials against your original remote definitions. |
| Local npm repository | pulp_npm hosted repository, populated with npm publish or yarn publish | Clean | pulp_npm is 0.10.2. Republishing internal packages is documented, so confirm scope names and dist-tags survive the move. |
| Remote npm repository (registry.npmjs.org) | pulp_npm remote with pull-through caching | Clean | Pulp mirrors upstream npm registries. Test lockfile resolution against the new endpoint before cutover. |
| Local and remote Python (PyPI) repositories | pulp_python hosted and remote repositories | Clean | pulp_python is 3.37.1, past version 1.0. Verify index URLs in pip and build tool configuration after repointing. |
| Cargo (Rust) repositories | pulp_rust, a tech preview | Gap | pulp_rust is labeled tech preview with APIs that may change, and authentication, authorization and full registry syncing are not yet supported. Keep Cargo on Artifactory or another host until this changes. |
| Virtual repository aggregation | No one-to-one match in Pulp | Gap | Pulp serves distributions from individual repositories, so a single URL that merges several sources needs a redesign of client configuration. Confirm how each team resolves packages today. |
| Checksum verification on download | Pulp content stores checksums per artifact | Needs rework | Downloads with the JFrog CLI verify checksums by default. Compare checksums after upload and run a sample install from each repository. |
The migration sequence from inventory to decommission
This sequence moves non-container repositories from Artifactory into Pulp in stages, with each step producing a checkable output. Teams finish with a verified copy of hosted content, Pulp remotes that match the original upstreams, a parallel run and a documented decommission of the Artifactory repositories.
Inventory repositories, upstreams and consumers
The platform team lists every non-container repository in Artifactory, including its package type, whether it is local, remote or virtual, its upstream URL, its approximate storage size and the CI jobs and developer workstations that resolve from it. Owners of each repository confirm which ones are still used. The output is a spreadsheet with one row per repository and a named owner, and the team confirms the list against the Artifactory administration console rather than relying on memory.
Run a pilot with a single package format
The team picks one format, typically a low-risk Maven or npm repository with a small number of consumers, and migrates only that repository. The pilot tests the full path from download to publish and resolve in a non-production build pipeline. The output is a signed-off pilot record listing the packages moved, the checks run and any plugin gaps found, which then informs the rest of the plan.
Download hosted artifacts with the JFrog CLI
An engineer runs jf rt download (or jf rt dl) against each hosted repository, using wildcard patterns or a JSON file spec to pull the files to a staging volume. The CLI verifies checksums by default, and it keeps the repository folder hierarchy unless the --flat option is set, so the default should be kept for Maven and npm layouts. The output is a local copy whose file count and checksum results match the inventory for that repository.
Upload hosted content into Pulp repositories
The team creates a Pulp repository for each format with the pulp-cli tool or the REST API under /pulp/api/v3/, then uploads the staged artifacts. For Maven, the team confirms the upload path against pulp_maven documentation, and for npm, packages can be republished with npm publish. Because the Maven Deploy Plugin in pulp_maven does not use authentication and does not separate SNAPSHOT and release repositories, uploads should use an approved path. The output is a Pulp repository whose content count matches the staged copy.
Recreate remotes against the original upstreams
For each remote repository, the team creates a Pulp remote that points at the same upstream the Artifactory remote used, such as Maven Central or registry.npmjs.org, and enables pull-through caching where the plugin supports it. Engineers then resolve a set of known dependencies through the new endpoints. The output is a test log showing that each dependency resolves from the Pulp remote with the same version and checksum as before.
Run Artifactory and Pulp in parallel
Build pipelines are pointed at Pulp in a staging environment while Artifactory stays live for production builds. The team compares build results, resolved versions and download timings across both systems over an agreed window, and it logs every package that resolves differently. The output is a discrepancy register with each item either fixed or accepted by its owner, and sign-off from the teams that consume each repository.
Cut over consumers and decommission Artifactory
Once the parallel run is clean, the team updates package manager configuration, CI variables and developer settings to the Pulp endpoints, and it keeps the Artifactory repositories read-only for a rollback period. After rollback risk is accepted, the team archives the final export, revokes service credentials and removes the repositories. The output is a decommission record showing which repositories were retired, where their archives are stored and who approved the change.
How to get hosted artifacts and remote definitions out of Artifactory
Start by inventorying what sits in Artifactory before moving anything, because hosted artifacts and remote definitions travel by different paths. Hosted content (the Maven, npm and Python packages your teams published into local repositories) can be downloaded with the JFrog CLI command jf rt download, which is also available as jf rt dl. The command accepts wildcard patterns or JSON file specs, verifies checksums by default and keeps the repository folder hierarchy unless --flat is set. Keep the hierarchy for migration so that Maven group and artifact paths and npm tarball names stay recognizable when you upload them into Pulp. Run the download against a test repository first and compare file counts and checksums with the source.
Remote definitions are not files, so they do not come out with the download. Capture each remote's URL, package type and any credentials from the Artifactory repository configuration, either through the Artifactory UI or the REST API. Record which upstreams each remote points at, such as Maven Central or registry.npmjs.org, and whether it uses a proxy or stored credentials. Those credentials are secrets, so move them into your secrets manager rather than a spreadsheet. Internal npm packages are different again: once you have the tarballs, republish them into the Pulp npm repository with npm publish or yarn publish, using a token issued by Pulp. Confirm which package metadata, such as versions and dist-tags, you need to preserve.
Export options differ between SaaS and self-managed deployments, so confirm your tier's capabilities with JFrog before you plan the cutover. Ask whether your subscription includes system or repository export, what metadata it carries, and whether your deployment is in scope for those features. If the export tooling is not available to you, the CLI and REST API download path described above is the fallback, and it will not carry permissions, properties or build information. Write those gaps into the migration plan and decide who will recreate access rules in Pulp. Note also that Pulp's Maven deploy path does not use authentication, so the republish step needs its own access control design.
How the migration changes by starting point and team size
A small estate with a handful of Maven or npm repositories owned by one team usually has the simplest path. The work centers on downloading hosted artifacts with the JFrog CLI, uploading them into Pulp, and recreating a few remotes against the original upstreams. Because there are few consumers, cutover can be scheduled with the owning team and tested in one pass.
- Inventory first: List each local, remote and virtual repository and mark which ones are actually used by builds.
- Small upload set: Downloads with
jf rt dlkeep the folder hierarchy, so the Pulp upload step can mirror the original layout. - Remotes to recreate: Point each Pulp remote at the same upstream the Artifactory remote used, such as Maven Central or the npm registry.
- Deploy behavior: Confirm how the team publishes Maven projects, since the pulp_maven deploy path does not use authentication.
- Single build owner: Update the one pipeline's repository URLs and credentials in a single change window.
Before cutover, confirm the Pulp plugin versions your formats need and check that the team is comfortable running the Pulp services.
A large estate with many teams usually depends on virtual repositories that aggregate local and remote sources behind one URL. Replacing that pattern is the main design decision. Pulp uses remotes and distributions rather than virtual repositories, so teams must agree on which URL each build tool will use after cutover and how shared resolution order is preserved.
- Virtual repository mapping: Document every virtual repository, its member repositories and the resolution order that builds rely on.
- Ownership by team: Assign an owner for each Pulp repository and each remote so credential and upstream changes have one approver.
- Staged cutover: Move non-critical repositories first and keep Artifactory read-only for rollback until consumers confirm.
- Publish paths: Standardize how internal Maven and npm packages are published, because deploy authentication and SNAPSHOT separation need controls around them.
- Operations capacity: Plan for the PostgreSQL, storage and worker services Pulp needs to run at this scale, and confirm them with the team that will operate them.
Confirm with each team which virtual repositories they depend on before writing the cutover plan.
A hybrid estate runs Harbor for OCI images and Helm charts while Pulp takes over Maven, npm and Python content. The split keeps each tool on the content it handles best, but it also means two registries, two sets of credentials and two sets of upgrade and backup procedures. The migration plan must treat them as one change with two tracks.
- Shared identity model: Decide how users and CI systems authenticate to Harbor and Pulp, and whether one identity provider backs both.
- Separate cutover tracks: Move containers under the Harbor track and packages under the Pulp track so a delay in one does not block the other.
- Build pipeline changes: Each pipeline may now pull from two hosts, so list every endpoint and secret it uses.
- Scanning gaps: Image scanning in Harbor and package tracking in Pulp are separate, so confirm how findings reach your security team.
- Operational ownership: Assign who patches, backs up and restores each service.
Before starting, confirm that the Pulp plugins for your package formats are in the maturity band you accept, and check the Harbor migration path for the container side.
How Pulp serves packages after the move
Once the packages are in Pulp, every client request runs through three services that you size and scale separately: pulpcore-api, a Django REST application served by gunicorn that handles uploads, remote and repository configuration and the REST API at /pulp/api/v3/; pulpcore-content, an aiohttp server that answers the Maven, npm and Python download requests from your build tools; and pulpcore-worker processes that run the sync, publish and cleanup tasks. All three rely on PostgreSQL as the single source of truth for tasks, so the database is the component most likely to become a shared bottleneck, and it needs its own sizing, backup and failover plan. Pulp documents that each service scales horizontally for high availability, but the number of workers and content replicas that your traffic needs is something to measure in a pilot, not assume.
Pulp's pull-through model works differently from Artifactory's remote repositories. A pulp_maven or pulp_npm remote points at the original upstream, such as Maven Central or registry.npmjs.org, and content is cached on first request. Your clients never talk to the upstream directly, but the first fetch of each artifact still depends on upstream availability, so confirm how your builds behave during an upstream outage. Before cutover, decide which internal packages are published with npm publish or the Maven Deploy Plugin into hosted repositories, and remember that the Maven deploy path does not authenticate and does not separate SNAPSHOT and release repositories, so access control has to sit in front of Pulp.
Content reaches clients through a distribution. After a sync or upload creates a repository version, a publish step produces the metadata that a client needs, and a distribution maps a base path to that publication so that clients resolve it as a normal repository URL. Plan one distribution per repository you migrated and test that a version rollback is visible to clients. Storage is the other sizing decision: artifacts and published content live in the backend you configure, so choose between local filesystem and object storage before loading data, and confirm the options in the Pulp storage configuration guide. Ask your team to estimate artifact volume from the Artifactory storage report, then size object storage and database growth from that figure.
What usually goes wrong with Maven deploy and plugin gaps
Most failed Pulp cutovers for Maven and other package formats trace back to a few known gaps rather than to the data move itself. The cards below cover the deploy path, plugin maturity, client configuration, virtual repository aggregation and post-upload verification. Each one names a check to run before cutover.
Unauthenticated Maven deploy path
The pulp_maven Deploy Plugin does not use authentication, and it does not separate SNAPSHOT and release repositories. Anyone who can reach the endpoint could publish into a repository your builds trust. Before cutover, place the Pulp endpoint behind your network controls and an authenticating proxy, and confirm which team owns publish rights. Test that a release artifact cannot be overwritten by a snapshot deploy.
Pre-1.0 plugin APIs
pulp_maven is at 0.35.0 and pulp_npm at 0.10.2, so their APIs may still change between releases. A scripted migration that works today can break after a routine plugin upgrade. Pin exact plugin versions in your Pulp deployment, record them in your runbook, and rerun the migration scripts in a staging environment before each upgrade.
Build configs still pointing at Artifactory
Maven settings.xml, pom.xml repository blocks, .npmrc files and Python index URLs often hold hard-coded Artifactory hostnames and credentials. Builds that still resolve against Artifactory keep working during cutover, then fail when the instance is retired, or silently drift to different versions. Inventory these files across repositories and CI templates, then change them in one reviewed batch.
Missing virtual repository aggregation
Artifactory virtual repositories let one URL serve local, remote and release content together. Pulp has no direct one-to-one equivalent in the supplied material, so a single resolution point may need to become several endpoints or a proxy layer. List every virtual repository your teams use, map each member, and test that a build resolves the same artifacts from the new endpoints as it did before.
Unverified checksums after upload
Uploads and syncs can succeed while metadata such as Maven checksums, npm packuments or Python simple indexes are incomplete or inconsistent. Consumers then fail on checksum mismatch or resolve stale versions. For a sample of artifacts per format, compare SHA-1 and SHA-256 values against the originals downloaded with the JFrog CLI, and confirm clients resolve the same versions before decommissioning Artifactory.
What drives the cost and duration of this migration
This table lists the factors that most change the effort of moving non-container repositories from Artifactory to Pulp, why each one matters and how to keep it under control. Use it to scope the work before asking for a fixed-scope quote, since most drivers multiply each other across formats and pipelines.
| Driver | Why it changes effort | How to keep it down |
|---|---|---|
| Repositories and formats | Each Maven, npm or Python repository needs its own Pulp remote, distribution and validation, and format plugins differ in maturity. | Inventory every repository, retire unused ones first, and migrate one format at a time starting with the most stable plugins. |
| Virtual repositories | Artifactory virtual repositories aggregate several local and remote sources, and Pulp has no one-to-one equivalent, so resolution order must be redesigned. | Map each virtual repository to its real upstreams, then decide whether clients can point at a single Pulp distribution or need several. |
| Hosted artifact volume | Downloading with the JFrog CLI, checksum verification and re-upload all scale with total bytes and file count, and sync time grows with content size. | Migrate by repository, prioritize active release artifacts, and confirm which historical versions must survive cutover. |
| Storage backend | Pulp content is served through its own storage configuration, so the choice of filesystem or S3-compatible backend affects capacity planning and transfer speed. | Settle the storage backend early, size it from the inventory, and confirm the configuration against the Pulp storage guide. |
| CI pipelines and client configs | Build tools, developer settings and deployment jobs each hold Artifactory URLs and credentials that must be found and changed. | Search repositories and pipeline definitions for Artifactory hostnames, and cut over one pipeline group at a time with a rollback path. |
| Maven deploy workflow | The pulp_maven deploy feature does not use authentication and does not separate SNAPSHOT and release repositories, so publishing jobs need redesign. | Decide how internal publishing is secured outside Pulp, and confirm the current deploy behavior with the pulp_maven documentation before writing jobs. |
| In-house Pulp operating skills | Running Pulp requires PostgreSQL, pulpcore API, content and worker services, and familiarity with its REST API and CLI, which many teams do not yet have. | Train operators before cutover, run a parallel environment, and ask any implementation partner to document runbooks as part of the written scope. |
Questions teams ask before moving from Artifactory to Pulp
What does moving from Artifactory to Pulp cost, and what drives the total?
The total depends on the work involved rather than on a single license line, so expect the cost to be driven by how many formats and repositories you move, how much remote and virtual repository logic must be recreated, and how much of your CI and build configuration changes. Cost has four parts: the infrastructure to run Pulp (compute, PostgreSQL, Redis, and object storage for content), the staff time to rebuild and test repositories, the ongoing operation and upgrades, and any external help you buy. Pulp itself is GPLv2+ licensed, so there is no per-server or per-component software fee. Ask any implementation partner for a fixed-scope quote built from an inventory of your repositories, formats and upstream sources. For the commercial side, compare against your current JFrog subscription terms, which JFrog publishes on its pricing page and which you should confirm with JFrog directly.
How long does a migration from Artifactory to Pulp take?
No supplied figure sets a duration, so the honest answer is that it depends on the number of repositories, the volume of hosted artifacts, and how many formats need custom handling. Plan the work in phases: inventory repositories, download hosted artifacts with the JFrog CLI, rebuild Pulp repositories and remotes, re-point build tools, and run both systems in parallel until consumers have moved. Maven, npm and Python are the formats with documented Pulp workflows, while plugins at 0.x maturity may need extra validation. Ask for a written timeline that names the formats in scope, the test cycles, and the cutover window before any work starts.
What does our internal team have to provide during the migration?
Your team needs to supply the people who own each repository, the build pipelines that resolve from Artifactory, and access to JFrog and your Pulp environment. In practice that means a list of repositories with owners, the upstream sources each remote proxies, the credentials and network paths your builds use, and sign-off on test results. Someone must also decide how internal Maven SNAPSHOT and release artifacts will be handled, because pulp_maven's deploy feature does not separate them. Confirm the staffing model and approval steps in the written scope so that developers can keep shipping during the cutover.
Can our own engineers run the migration without an outside partner?
Yes, a capable platform team can do this internally, but it needs people who can operate PostgreSQL, object storage and Kubernetes or Docker Compose, plus engineers who understand Maven, npm and Python build behavior. Pulp runs three services, pulpcore-api, pulpcore-content and pulpcore-worker, and each scales horizontally, so operational skill matters as much as migration skill. Pulp's official images include a multi-process image for simpler setups and single-process images for Compose or Kubernetes. If your team lacks this experience, a fixed-scope engagement can cover the build, hardening and handover, while retainers cover upgrades. Confirm the scope in writing before deciding.
Do all of our Artifactory formats move to Pulp?
No. Pulp covers Maven, npm, Python, RPM, Debian, file and others through plugins, but Artifactory supports more than 60 package types, so you must map each format you use against a Pulp plugin. Plugin maturity also varies: pulp_python and pulp_rpm are past 1.0, while pulp_maven and pulp_npm are still 0.x, and the Rust plugin is a tech preview that does not yet support authentication or full registry syncing. Container images belong in Harbor rather than Pulp, because Harbor's Artifactory adapter is the more direct route for images. Build your format inventory first, then confirm each plugin's status with the Pulp maintainers before cutover.
How is Maven deploy authentication handled in Pulp?
Pulp's Maven Deploy Plugin path does not use authentication, and it makes no distinction between SNAPSHOT and release repositories. That means you cannot rely on the deploy feature alone to restrict who publishes artifacts. Teams typically keep Pulp's deploy path off the open network, place an authenticating reverse proxy or network policy in front of it, and enforce publish rules in CI. Confirm with the pulp_maven maintainers whether authenticated deploy is on their roadmap, and document your compensating controls for security reviews before go-live.
What happens to container images already stored in Artifactory?
Container images are outside the Pulp path. Images and Helm charts should move to Harbor, which the migration sibling pages cover through replication, proxy cache projects and credential changes. Pulp's pulp_container plugin can sync images from any registry that implements the registry API, but Harbor's documented Artifactory adapter is the more direct route. Keep Artifactory-hosted images available until every pipeline and Kubernetes image pull secret points at the new registry. Confirm the image cutover plan separately, because it has its own dependencies and test steps.
What a DeployOpen engagement covers for this migration
A DeployOpen engagement for this migration starts with a written scope that names the Artifactory repositories in question, the Pulp plugins that will serve them, the upstreams each remote will point at, and the cutover window agreed with your teams. Work begins only after that scope, its deliverables and its timeline are confirmed in writing. The first working phase is an inventory: every local, remote and virtual repository, its package type, its download volume and the consumers that pull from it, including CI jobs, build agents and developer machines that hold repository URLs in configuration files such as settings.xml or .npmrc.
From that inventory, DeployOpen builds Pulp remotes for Maven, npm and Python content against the original upstreams, then tests each one with the same package requests your builds make today. Maven remotes are checked against the deploy behavior documented for pulp_maven, since that deploy path does not use authentication and does not separate SNAPSHOT and release repositories. Your security team should decide in advance how those gaps are handled, whether through network controls, a separate publish path or a different internal workflow. Each plugin's maturity is also checked against the version your team has approved.
During the parallel period, builds can point at both systems while the team compares checksums and resolution results. DeployOpen supports the cutover itself, including repointing build configuration and rolling back if a consumer fails. Ongoing support, upgrades and recurring testing are available as a retainer, which is usually the right choice for teams that will run Pulp without a dedicated plugin maintainer. Ask any provider to confirm the response terms, upgrade approach and who holds administrator access in your environment before signing.
How DeployOpen scopes, runs and supports the Pulp migration
DeployOpen plans, implements, integrates, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, so a Pulp rebuild runs in your cloud account or data center. Engagements are fixed-scope, and the scope, deliverables and timelines are agreed in writing before any migration work starts.
How we scope
- Inventory every Artifactory Maven, npm and Python repository, its remote upstreams and its consumers before any work starts
- Record which repositories are local, remote or virtual, and which virtual aggregations need a decision
- Flag Pulp plugins still at 0.x or tech preview against the formats your teams actually use
- Agree the written scope, deliverables and timeline with you before migration work begins
How we build
- Deploy Pulp services and PostgreSQL in your environment, with storage and backups configured to your standards
- Download hosted artifacts with the JFrog CLI, verify checksums, and upload them into Pulp repositories
- Recreate remote repositories as Pulp remotes pointed at the original upstreams and test pull-through behavior
- Test Maven deploy, npm publish and Python upload paths, including the Maven deploy gap around authentication
How we hand over
- Document repository layout, remote configuration, publishing workflows and access controls for your team
- Provide runbooks for routine operations, restores and upgrades of the Pulp services
- Walk your engineers through cutover steps, client repointing and rollback criteria
- Deliver the migration record so your auditors and internal reviewers can trace each repository
How we support
- Support after handover is available as a retainer, covering patching, upgrades and monitoring of Pulp services
- Retainers can also include continuous security testing of the repository and publishing paths
- Ask us to confirm the retainer scope, response expectations and upgrade handling in the written quote
- Plugin version changes are reviewed before upgrades so your build pipelines are not surprised

