Sell subscription-gated access to a private repo with VBWD’s GHRM plugin: connect a GitHub App, tie packages to plans, auto-issue deploy tokens and collaborator invites on activation, and auto-revoke on cancel.
A practical, step-by-step guide.
You have a private repository that other people would pay to use: a trading library, a set of Terraform modules, a game engine, a scraper toolkit. The problem is not the code. The problem is billing, access control, and revocation. You do not want to hand-invite every buyer, chase renewals in a spreadsheet, or leave ex-customers with commit access after they stop paying.
This guide walks through turning a GitHub repository into a subscription-gated product using VBWD and its GHRM plugin. VBWD is a self-hosted, source-available platform (Python/Flask, PostgreSQL, Vue 3, Docker) built on an agnostic core: features arrive as plugins that extend the platform through an event bus instead of editing core code. GHRM (“GitHub Repo Manager”) is the plugin that connects a subscription to real GitHub access.
What you will have at the end
A public catalogue page listing your packages. A customer picks a plan, pays, and is automatically invited as a collaborator on the matching private repository, with a deploy token issued for CI use. When they cancel or their subscription lapses, access is revoked after a grace period. README, CHANGELOG, and release notes stay in sync with GitHub. You never touch the GitHub UI to grant or remove access by hand.
Prerequisites
- A running VBWD instance you control (self-hosted via Docker). If you have not stood one up yet, start from the architecture overview to understand the core-plus-plugins model before you install.
- A GitHub organization that owns the private repositories you want to sell. Collaborator invitations and App installations are cleaner at the org level than on a personal account.
- Permission to create a GitHub App in that org, including generating a private key (PEM file).
- At least one tarif plan defined in VBWD to attach packages to. Pricing and plan mechanics are covered in the pricing documentation.
- Basic familiarity with the admin backoffice: enabling plugins, editing plugin config, and reading logs.
Step 1: Enable the GHRM plugin
GHRM ships as a plugin (or as part of a bundle). In the admin backoffice, open the plugins list, find GHRM, and enable it for the backend. Enabling a plugin registers its routes and subscribes its handlers to the event bus. Nothing in core changes; the plugin listens for subscription lifecycle events and reacts to them.
Confirm the plugin’s blueprint is mounted by checking that its admin routes respond. A common early mistake is assuming a green health check means the plugin loaded. It does not. Verify GHRM specifically appears as enabled in the backend plugin manifest, then restart the API container so the state is read cleanly. You can browse the full catalogue of available plugins on the plugins page.
Step 2: Create and configure the GitHub App
GHRM talks to GitHub through a GitHub App rather than a personal token, so access is scoped and auditable. In your GitHub org settings, create a new App and grant it the repository permissions it needs: read and write on Administration (to manage collaborators) and read on Contents and Metadata (to sync README, CHANGELOG, and releases). Install the App on the org and select the repositories you plan to sell.
Generate a private key. GitHub downloads a PEM file. This is the single most error-prone part of the whole setup. GHRM authenticates as the App using that PEM, and it locates the file by an exact path and filename you configure. If the path or filename is wrong, or if you point GHRM at the OAuth client credentials but the App itself is private and not installed on the target repos, invitations fail with a 404 rather than a clear permission error.
Record four values in the GHRM plugin config: the App ID, the OAuth client ID and secret (if you also use OAuth for the customer-facing login flow), the installation’s org, and the absolute PEM path inside the container. Mount the PEM into the API container as a file, not baked into the image. After changing any config slug, restart the API container; GHRM reads its GitHub client configuration at startup.
Step 3: Define your catalogue of packages
A “package” in GHRM maps one sellable unit to one or more GitHub repositories and ties it to a plan. For each package you define: a slug, a display name, the target repository (org/repo), the collaborator permission level to grant (typically read or write), and the tarif plan that unlocks it.
Keep the mapping explicit. If your “Pro” plan grants access to three repos, list all three against that package. If you sell a starter tier with one repo and a full tier with five, define two packages against two plans. Because plans and pricing live in core and packages live in the plugin, you can restructure your pricing without rewriting the GitHub integration. The platform documentation covers how plans, subscriptions, and plugin-defined sellables relate.
Step 4: Wire access to subscription lifecycle events
This is where the automation lives, and you get it without writing glue code. GHRM subscribes to the subscription lifecycle events that core emits on the event bus:
- On
subscription.activated: GHRM issues a deploy token for CI or automated pulls and sends the customer a GitHub collaborator invitation to each repo in the purchased package, at the configured permission level, via the GitHub API. - On cancellation or expiry: GHRM schedules revocation. After a configured grace window, it removes the collaborator and invalidates the deploy token.
The grace window matters. Payments retry, cards expire and get updated, and you rarely want to cut a paying customer off the instant a renewal is late. Set the grace period to match your dunning policy, for example a few days, so a transient billing failure does not lock someone out mid-work. Everything here rides the event bus, so core stays agnostic and GHRM stays the only component that knows about GitHub.
Step 5: Sync README, CHANGELOG, and releases
Buyers evaluate before they subscribe, so your catalogue should show current documentation without exposing the source. Configure a GitHub Actions workflow in each sellable repo that pushes README, CHANGELOG, and release metadata to your VBWD instance on every release or documentation change. GHRM ingests that content and renders it on the catalogue, so what a prospect reads always matches what is actually shipped.
Because this runs on GitHub Actions inside the source repo, the private code never leaves GitHub; only the documentation surface you choose to publish is sent over.
Step 6: Publish the catalogue page
Present the packages through a CMS catalogue page on your instance. Each entry shows the name, the synced description and CHANGELOG, the plan required, and a subscribe action that routes into the standard checkout. The catalogue is a normal CMS page, so you can style it, add marketing copy above it, and place it in your navigation like any other page.
Verification: test the full loop before you sell
Do not announce until you have watched one subscription travel the entire path. Use a test account:
- Subscribe the test user to a plan that unlocks a package. Confirm core emits
subscription.activatedand that GHRM logs the collaborator invite and token issuance. - Check the target repo on GitHub: the test account should have a pending or accepted collaborator invitation at the expected permission level.
- Accept the invite from the test account and confirm it can clone with the issued token.
- Cancel the subscription. Confirm revocation is scheduled, then advance past the grace window and confirm the collaborator is removed and the token is dead.
- Push a release in the source repo and confirm the CHANGELOG on the catalogue updates.
If invites never arrive, the first suspect is always the GitHub App: wrong PEM path or filename, the App not installed on that specific repo, or a private App where you expected a public one. Check the API logs for the GitHub client initialization and the API response code on the invite call. A 404 on invite almost always means the App cannot see the repo, not that the customer’s username is wrong.
Limits and honest caveats
Be clear with yourself about what this does and does not do.
- You are bound by GitHub’s model. Access is granted through GitHub’s collaborator and invitation system and subject to GitHub API rate limits. At high volume, batch operations and back off on rate-limit responses; GHRM cannot invite faster than GitHub allows.
- Revocation is not instant. It happens after the grace window you set. That is a deliberate trade for billing resilience, not a security guarantee of immediate cutoff.
- Gating controls ongoing access, not history. Removing a collaborator stops future pulls and updates. It does not retroactively delete a copy someone already cloned. If your value is in continuous updates and support, this model fits. If your value is a single static download that must never be re-shared, subscription gating is the wrong tool.
- Configuration is unforgiving. The GitHub App must be set up correctly, PEM path and filename exact, public-versus-private chosen deliberately, and installed on the right repos, or invitations silently 404.
Licensing note
VBWD itself is source-available under BSL 1.1: free to run commercially while your annual VBWD-attributable sales stay below the value of 6.7 BTC, above which a commercial license applies. It is not public domain and not CC0. That governs the platform you are running; the license terms of the code you sell through it are entirely your own choice.
Takeaway
Selling access to a private repo comes down to four moving parts: billing, an access grant, a revocation, and a shopfront. GHRM binds them to subscription lifecycle events so the flow runs without manual invites or renewal chasing, while core stays agnostic and your GitHub source stays on GitHub. Get the GitHub App configured correctly, set a grace window that matches your dunning, and test the full activate-to-revoke loop once before you take money. After that, a new subscriber becomes a collaborator on their own, and a lapsed one stops being one, without you opening the GitHub UI.
Learn more about VBWD
VBWD is a self-hosted, source-available platform for building subscription products, marketplaces, and AI-powered apps. Explore it further:
- 🌐 Website and documentation: vbwd.cc — see the plugins, architecture, and developer docs.
- 💻 Source code and plugins on GitHub: github.com/VBWD-platform
- 🎥 Watch VBWD in action: demo video 1 and demo video 2
- 💼 Follow the project on LinkedIn: linkedin.com/company/vbwd
VBWD is source-available — get the SDK on GitHub.