How to Create and Use Private Pods with CocoaPods

A practical guide to packaging your own internal code as a private pod, hosting a private spec repo, and reusing shared modules across multiple iOS apps.

Why Private Pods

As an app grows, you often want to share code across multiple projects: a networking layer, a design system, or analytics helpers. Copying files between projects quickly becomes unmaintainable.

A private pod packages that shared code as a proper CocoaPods dependency that only your team can access. Each app then declares it in a Podfile like any other pod.

This brings versioning, reproducibility, and clean separation to internal code. Teams can iterate on a shared module and roll it out to consumers deliberately.

The mechanics reuse everything CocoaPods already does for public libraries. The main additions are a podspec that describes your module and a private location to host it.

Understanding the Podspec

A podspec is the metadata file that tells CocoaPods how to build and integrate a library. Every pod, public or private, has one.

It declares the pod's name, version, supported platforms, source files, dependencies, and where the source lives. CocoaPods reads it to know exactly what to fetch and compile.

For a private pod, the source usually points to a private Git repository that your team controls. Version numbers typically map to Git tags.

Getting the podspec right is most of the work. You can validate it locally with pod lib lint, which checks that the spec is well formed and that the pod builds in isolation.

Step 1: Scaffold the Pod

CocoaPods can generate a starter library structure for you with pod lib create followed by your pod name. It sets up a folder layout, an example app, and a template podspec.

The generated example app is genuinely useful. It lets you develop and test your module in a real Xcode target before publishing anything.

Move your shared source files into the pod's source directory, and update the podspec to reference them. Keep the module focused on a single responsibility.

Open the example workspace, build, and confirm your code compiles cleanly in that isolated context. Fixing problems here is much easier than after other apps depend on it.

Step 2: Set Up a Private Spec Repo

Public pods are indexed in the central CocoaPods trunk. For private pods you instead host a private spec repository, which is just a Git repo containing your podspecs.

Register it locally with pod repo add followed by a name and the repo's Git URL. This tells your machine where to look for private pod definitions.

Your whole team adds the same private spec repo, typically hosted on your company's Git platform with access controls. Only people with repository access can resolve the pods.

This keeps proprietary code private while still using the familiar CocoaPods workflow. Nothing is published to the public index.

Step 3: Tag and Publish a Version

Versioning a private pod is driven by Git tags. Set the version in the podspec, commit your changes, then create a matching Git tag such as 1.0.0 and push it.

Once the tagged source exists, push the podspec to your private spec repo with pod repo push, naming your repo and the podspec file. CocoaPods validates and stores the spec.

From that point, the version is available to any consumer that has the private spec repo configured. Treat published versions as immutable and bump the number for every change.

Keep a short changelog. Consumers upgrading across versions will thank you for clear notes on what changed and any migration steps.

Step 4: Consume the Private Pod

In a consuming app's Podfile, add a source line at the top pointing to your private spec repo, in addition to the public CocoaPods source if you also use public pods.

Then declare the pod normally inside your target, for example pod 'YourInternalModule', '~> 1.0'. Version constraints work exactly as they do for public pods.

Run pod install, open the .xcworkspace, and import the module. Your shared code is now a versioned dependency rather than copy-pasted files.

When you release a new version of the module, consumers move forward deliberately with pod update for that specific pod, keeping upgrades controlled.

Practical Tips

Keep each private pod small and single-purpose. Large catch-all modules become as painful as the copy-paste problem you were trying to solve.

Validate before publishing. Running pod lib lint locally catches most integration issues before they reach other teams and break their builds.

Document access requirements clearly. New teammates need to know how to get access to the private spec repo and the source repositories, or their pod install will fail.

Use semantic versioning consistently so your ~> constraints behave predictably. Reserve major version bumps for genuinely breaking changes.

Testing and CI Considerations

Because your continuous integration servers also need to resolve private pods, they need access to both the private spec repo and the underlying source repositories. Plan credentials for CI early.

Many teams use deploy keys or machine accounts with read access so the build agent can clone private repositories without embedding a personal login. Store those secrets in your CI system rather than in the Podfile.

Run pod lib lint as part of the module's own pipeline so a broken podspec never gets published. Catching integration issues before a version is tagged saves every consumer from a broken build.

When you bump a version, consider testing it against at least one real consuming app before announcing it. A quick end-to-end check confirms the published spec, the Git tag, and the source all line up.

Honest Limitations

Private pods add real infrastructure: a spec repo, access control, and a publishing discipline your team must follow. For a single small app, that overhead may not be worth it.

If your organization is already moving toward Swift Package Manager, note that SPM also supports private packages via Git, and you may prefer to standardize there for new modules.

Remember what this does and does not do. Private pods organize and share your own native code; they do not write features or replace Xcode.

And as always, distributing the resulting apps still requires building in Xcode and an active Apple Developer Program membership. CocoaPods only handles the dependency plumbing.

Authenticating Private Spec Repositories

Private pods usually live in a private specs repository, so access control matters.

Add the private spec repo with pod repo add, and make sure your machine can authenticate to it — typically via an SSH key registered with your Git host, or an HTTPS token.

Declare the source at the top of your Podfile alongside the public CDN source so CocoaPods knows where to resolve each pod.

On CI, the build agent needs the same access. Provide a deploy key or a scoped access token through your CI secrets rather than committing credentials, and confirm the agent can reach both the private specs repo and the pod source repositories before the build runs.

Frequently Asked Questions

What is a private pod?

A private pod is your own internal code packaged as a CocoaPods dependency, hosted in a private location only your team can access. It lets you share modules like a networking layer or design system across multiple apps with proper versioning.

What is a podspec?

A podspec is the metadata file describing a pod: its name, version, platforms, source files, dependencies, and source location. Every pod has one, and CocoaPods reads it to know how to fetch and build the library.

How do I host a private pod?

You create a private spec repository, which is a Git repo of your podspecs, and register it locally with pod repo add. Team members add the same repo, typically on your company Git platform with access controls, so only authorized users can resolve the pods.

How do I version a private pod?

Set the version in the podspec, create a matching Git tag such as 1.0.0, push it, then publish the spec with pod repo push. Treat each published version as immutable and follow semantic versioning.

Should I use private pods or Swift Package Manager for shared code?

Both support private, Git-hosted modules. Use private pods if your project is already invested in CocoaPods; consider SPM if you are standardizing on Apple's native tooling for new modules.