Skip to content

Managing Premium WordPress Plugins with Composer, Bedrock, and Private Repositories

Emnes
Illustration of composer.json manifest connected to premium plugin license

Every serious WordPress site ends up needing premium plugins. ACF Pro for custom fields on complex editorial sites. Gravity Forms for conditional-logic forms. WooCommerce Subscriptions for recurring billing. Yoast Premium, Rank Math Pro, WP Rocket, WP All Import Pro — the list goes on. All of these are paid products that are not on the WordPress.org plugin directory, which means they’re not in the default Composer repositories and you can’t just composer require wp-plugin/acf-pro.

If you’re using Bedrock, this is one of the first real obstacles you’ll hit. Premium plugins are exactly where “just zip it and upload to wp-admin” is tempting, and exactly where that approach quietly breaks your dependency discipline. This guide covers every practical way to install premium WordPress plugins via Composer — vendor-provided repositories, paid aggregators, private Satis instances, and manual package definitions — along with how to store license keys securely, handle plugin updates across multiple sites, and survive the occasional vendor endpoint change.

Why Not Just Upload the Zip?

The temptation with premium plugins is to download the zip, upload it to wp-admin, and move on. That works — once — and immediately breaks Bedrock’s core invariant: every piece of third-party code is declared in composer.json.

The specific failure modes:

  • Your next deploy wipes the plugin. Bedrock’s .gitignore excludes web/app/plugins/, so plugins installed via the admin aren’t in Git. When CI runs composer install on the server, it creates a new plugins/ directory with only the plugins in composer.json.
  • Nobody else on the team has the plugin. A new developer who clones the repo and runs composer install gets a broken site, because the plugin only exists on the server you uploaded it to.
  • There’s no version lock. You installed ACF Pro 6.2.8 on production, but the staging site has whatever zip someone uploaded six months ago. Debugging becomes impossible.
  • Updates become manual. Every plugin needs to be re-downloaded, re-zipped, and re-uploaded by hand on every site. Multiply by 20 sites and you’re spending a day a month on plugin updates.

The fix is to route premium plugins through Composer like everything else. The tools exist — you just have to learn which one fits each plugin.

Four Ways to Install Premium Plugins with Composer

In rough order of preference:

  • 1. Vendor-provided Composer repository — if the plugin vendor runs their own Composer endpoint.
  • 2. Paid aggregator — services like Deliciousbrains’ Composer repository.
  • 3. Private Satis repository — your own Composer repository for purchased plugins.
  • 4. Raw zip URL via package definition — last resort for plugins with no other option.

Option 1 — Vendor-Provided Composer Repositories

The cleanest option, when available. A growing number of premium plugin vendors run their own Composer endpoints that you point at with your license key. Examples as of April 2026:

  • ACF Proconnect.advancedcustomfields.com
  • Gravity Formsgravity.composer.rocketgenius.com
  • WP Rocketwp-rocket.me Composer endpoint
  • Yoast Premium — vendor-provided
  • WooCommerce Subscriptions and most Automattic premium extensions — via Packagist Commercial or direct vendor repo

Adding a Vendor Repository

In composer.json:

"repositories": [
  { "type": "composer", "url": "https://connect.advancedcustomfields.com" }
]

Then install:

composer require wpengine/advanced-custom-fields-pro

License Keys in auth.json

Your license key goes in auth.json at the project root, never in composer.json:

{
  "http-basic": {
    "connect.advancedcustomfields.com": {
      "username": "YOUR_ACF_LICENSE_KEY",
      "password": "example.com"
    }
  }
}

Critical:

  • Add auth.json to .gitignore immediately. Leaked license keys are a real and common problem.
  • Distribute it securely to your team — 1Password shared vaults, a Vault server, or encrypted config management (Trellis has Ansible Vault for this).
  • In CI, store the auth.json contents as an encrypted secret and write it to disk before composer install.

Option 2 — Paid Aggregators

If you have lots of premium plugins across multiple sites, a paid aggregator can consolidate licensing and Composer access. The two big names:

  • Deliciousbrains Composer repository — subscription service that hosts a curated set of premium plugins (the Deliciousbrains team maintains the packages). Good for teams who want a single bill and a single Composer endpoint for many plugins.
  • WPackagist Premium and other community-run mirrors — variable coverage, worth checking for specific plugins.

Configure the same way — add the repository URL, put credentials in auth.json, composer require each plugin.

Aggregators are convenient but come with tradeoffs: you’re paying a markup on the underlying licenses, and the aggregator can drop a plugin from their catalog if the vendor changes terms. For a small number of premium plugins, direct vendor repositories are usually better.

Option 3 — Private Satis Repository

When you’ve purchased a plugin directly from a vendor who doesn’t provide a Composer endpoint, the cleanest solution is to host your own Composer repository with Satis.

Satis is a static Composer repository generator. You give it a satis.json listing the packages you want to host and where to find them (usually Git repositories or direct zip URLs), run satis build, and it generates a static packages.json file that Composer can read.

A typical agency workflow:

  • Create a private GitHub repository for each premium plugin you’ve purchased. Push the plugin’s source code (with your license embedded via environment variables, not hardcoded).
  • Create a Satis config that lists all these repositories.
  • Host the generated Satis output somewhere — GitHub Pages, an S3 bucket, a dedicated server behind HTTP basic auth.
  • Point your projects at the Satis URL, add credentials to auth.json, and composer require as normal.

Downsides: you maintain the repository. Every plugin update means downloading the new version from the vendor, pushing to your Git, and rebuilding Satis. For one or two plugins it’s overhead; for ten it’s a real weekly task. Automation (a cron job that checks for updates, downloads new versions, and commits) can help.

Option 4 — Raw Zip URLs via Package Definition

The fallback for plugins with no Composer story at all. Add a package-type repository to composer.json:

{
  "type": "package",
  "package": {
    "name": "premium-vendor/premium-plugin",
    "version": "3.2.1",
    "type": "wordpress-plugin",
    "dist": {
      "type": "zip",
      "url": "https://vendor.com/premium-plugin-3.2.1.zip?license=XYZ"
    },
    "require": { "composer/installers": "^2" }
  }
}

This works, but:

  • The zip URL often contains your license key — don’t commit it to Git. Use environment variables and substitute at install time.
  • You have to bump the version string manually every time you want to update.
  • If the vendor changes their download URL scheme, your pipeline breaks.

Use this option when you have no choice. Migrate to Satis or a vendor repository when one becomes available.

Storing License Keys Securely

License keys are secrets. Treat them like database passwords:

  • auth.json in .gitignore — always. No exceptions.
  • Shared in a password manager — 1Password, Bitwarden, or a team vault.
  • In CI, injected as a secret environment variable and written to auth.json at install time.
  • On servers managed by Trellis, stored in Ansible Vault alongside database credentials.
  • Rotated when a team member leaves. If they had access to the vault, rotate.

Trellis 1.30+ added Composer custom-header authentication, which is useful for vendors that authenticate by HTTP header rather than HTTP Basic Auth. Check the Trellis changelog for the exact syntax.

Updating Premium Plugins

Updates work the same as for free plugins:

composer update wpengine/advanced-custom-fields-pro
composer update --no-dev --optimize-autoloader

Commit the updated composer.lock, test on staging, deploy to production. For teams running multiple sites, Renovate or Dependabot can automate the PR creation — both support private Composer repositories with authentication.

Since Bedrock 1.30, pairing Composer updates with WP Sec Adv gives you automated security advisories on every plugin — premium plugins included, as long as they’re in the Wordfence Intelligence feed.

Common Pitfalls

The Vendor Changes Endpoints

Vendor Composer endpoints occasionally change URLs or authentication methods. Monitor the vendor’s Composer documentation and follow their blog. When it happens, the fix is a composer.json and possibly auth.json update.

CI Doesn’t Have auth.json

If your CI fails with “could not authenticate against connect.advancedcustomfields.com”, you forgot to inject the secret. Every CI pipeline needs a step that writes auth.json from an encrypted environment variable before composer install.

License Expired

When a license expires, composer install fails silently or with a 401. Set calendar reminders for license renewals, or (for teams with many plugins) centralize license tracking in a spreadsheet or dedicated tool.

Plugin Supports Composer But Not Its Dependencies

Occasionally a premium plugin ships vendored dependencies that conflict with other plugins’ vendored dependencies. The Roots blog post on namespace prefixing with PHP-Scoper covers the mitigation. Short answer: plugin vendors should scope their dependencies; when they don’t, you can’t do much except report the issue.

Multi-Site License Terms

Most premium plugins license per-site or per-seat, not per-developer-using-Composer. Having a Composer-installable plugin does not make it legal to install on unlimited sites. Check vendor terms; some vendors have agency or unlimited licenses explicitly for Composer-based workflows.

A Real-World Example: Managing 20 Sites with Shared Premium Plugins

If your agency runs 20+ sites that share premium plugins, here’s a concrete workflow that scales:

  • Central Satis repository for any plugin without a vendor Composer endpoint. Automated update check job that downloads new plugin versions weekly.
  • Vendor Composer endpoints for ACF Pro, Gravity Forms, WP Rocket, Yoast Premium.
  • Central auth.json template stored in the agency password manager, distributed to developers on onboarding.
  • Ansible Vault for production server Composer credentials, distributed via Trellis.
  • Renovate bot configured across all site repos, opening PRs for plugin updates and batching them weekly.
  • License spreadsheet tracking every license key, renewal date, and which sites use it.

Total ongoing maintenance: about 2 hours per week for the lead developer. Before this workflow, we spent that many hours per site per month.

Frequently Asked Questions

Does every premium plugin support Composer?

No. A growing majority do via vendor-provided repositories, but some are still zip-file-only. For those, Satis or the raw zip URL approach is your fallback.

Can I commit auth.json if my repository is private?

Strongly recommended not to. Private repositories leak — through clone-to-public mistakes, compromised developer laptops, or acquisition events. Keep secrets out of Git regardless of repository visibility.

What if a plugin vendor’s license terms forbid Composer distribution?

Check the license. Some vendors explicitly forbid rehosting (even on a private Satis) because their update and anti-piracy mechanisms depend on their own distribution servers. Respect those terms — use the vendor’s own repository if they provide one, or the raw zip URL approach with URL rewriting on install.

How do I handle a premium plugin that’s bundled with a theme purchase?

Common with premium WordPress themes that bundle Revolution Slider or similar. Either use the theme vendor’s Composer repository if they have one, or treat the bundled plugin as a separate Satis entry if the theme license permits.

Can I use Dependabot or Renovate with premium plugin repositories?

Yes. Both support Composer and authentication. Configure the bot with the same credentials you use in CI, and it will open PRs for plugin updates automatically.

Premium Plugins the Right Way

Getting premium plugins into Composer is the single highest-leverage change you can make for maintaining a professional Bedrock workflow. Once every plugin is declared, versioned, and reproducibly installed, deploys become predictable, rollbacks are trivial, and onboarding a new developer drops from “three hours of zip uploads” to git clone && composer install.

At Emnes, all 18 of our production sites run with every plugin Composer-managed, across a mix of vendor Composer endpoints, Satis, and aggregators. If you want help setting up the same workflow for your agency, get in touch.

Related reading: the Bedrock complete guide, migrating to Bedrock without downtime, and our upcoming post on the full Roots stack.