· · 21 min read Intermediate

Your Dependency's Business Model Is Part of Your Threat Model

Portainer froze its free edition this month. HashiCorp did it to Vault in 2023, MinIO did it in four steps without touching the licence. Thirty-six dated cases, what each one cost, and five questions to score your own stack.

A girl pries a coin slot off a server with a screwdriver while a troll holds out its hand for coins

TL;DR A vendor freezing its free edition belongs in your risk register next to the expiring certificate. Thirty-six dated cases below, three kinds of event, and five questions to score your own stack. My own register had the Vault row missing for three years.

On 11 September, Portainer’s CEO published “Portainer 3.0 is coming, and here’s what it means for you”. I read it the Monday after and shrugged.

Here’s what it says. 3.0 is a Kubernetes-first codebase for enterprise customers, and “we are not cutting a separate CE build of it”. Community Edition stays on 2.x. 2.45 LTS “is the last release in the 2.x line”. A few days later they added a clarification: 2.45 keeps getting security fixes, bug fixes and back-ports of any 3.x feature that has a Docker API equivalent, “for as long as that LTS is supported”. The lifecycle page puts that at May 2027. Want 3.x for free? There’s a Business Edition key called 3 Nodes Free, one per organisation.

I want to be fair to Portainer, because the rest of this is going to sound like I’m not. Nothing in that post is sneaky. The licence on the code you’re running didn’t change. It’s still zlib, the repository says so. They explained themselves, they’re supporting what they shipped, and they wrote the uncomfortable sentence themselves: releasing 3.x as CE “would misrepresent what it is and who it is for”.

So if you run Portainer on a Docker host, you probably shrugged too. It still works. It’ll still work in May 2027.

That shrug is the whole post. It’s what a risk sounds like when nobody wrote it down.

The row my register was missing

I keep a risk register for client platforms. It’s a boring spreadsheet. Certificates that expire, a Debian release going end of life, a Kubernetes version that drops an API. Each row gets a date, a blast radius, and a rough cost to get out. Nobody argues about those rows. They’ve all happened to someone in the room.

Here’s the Portainer news as one of those rows:

Risk. The vendor of the container management UI freezes the free edition.

Likelihood. High. The vendor sells a commercial edition, and no foundation owns the code or the name.

Impact. The upgrade path acquires an invoice or a node cap. The free edition receives security fixes until a date the vendor sets.

Trigger. A blog post.

Mitigation. Know the exit before the post. Keep the data in a format the alternative reads.

I’d never seen that row in anyone’s register. Mine included, until this month. We treat the licence on a dependency like the licence on the kernel, something that’s just true. Then a company changes it in a quarterly planning meeting and everyone’s surprised.

Now imagine you’d written that row down in 2024. The Portainer post lands and you already know the answers. 3 Nodes Free covers you if you run three environments or fewer under one organisation. You might not care about 3.x at all, since a Docker home lab isn’t who it’s for. And if you ever want out, Komodo and Arcane both read compose stacks, though neither’s a fork. Ten minutes of reading, and you’re back to whatever you were doing.

Thirty-six rows, three kinds of event

So I built the register I wish I’d had. I went through every case I could remember and a few I’d forgotten, and read each one on the vendor’s own page on 23 September 2026. Anything I couldn’t confirm there, I dropped. That left forty-three events. Some fold into each other, a reversal belongs with the move it reversed and a second relicensing with the first. Thirty-six rows.

DateProjectWhat changedThe free path todayFork
2016-08-16MariaDB MaxScaleGPLv2 to BSL, the licence’s first use anywhere, seven years before HashiCorp reached for it. “The license of MaxScale has been changed from GPLv2 to MariaDB BSL”Converts to GPL after four yearsNone
2018-08Redis modulesAGPL to Apache-2.0 with the Commons Clause, then RSAL in February 2019The server stayed BSD until 2024None
2018-10-16MongoDBAGPLv3 to SSPLFree to self-host. The OSI said in 2021 it is not open sourceNone survived
2018-11-29Neo4j EnterpriseEnterprise source out of the repository with 3.5, “requires a commercial license”Community stays GPLv3
2018-12Emby4.x closed source, by the fork’s account3.5.2 was the last GPL releaseJellyfin, from 3.5.2. 12.1 this month
2018-12-14Confluent PlatformKSQL, Schema Registry and REST Proxy from Apache-2.0 to the Confluent Community LicenseFree to run, no SaaSNot a fork question. Kafka itself stays Apache-2.0 at the ASF
2019-11-06SentryBSD-3 to BSL , then to FSL in 2023Free to self-host, competing SaaS excluded, converts to Apache-2.0 or MIT after two yearsNone
2019-12-04ChefBinaries behind the Chef EULASource stays Apache-2.0Cinc, “same code, same compatibility, no EULA”. 19.3.14 in May
2020-04-30AnacondaTerms of service on the package repositoryFree under 200 employees, the line since 2024Not a fork question. Miniforge and conda-forge, free for everyone
2020-05-26CoreOS Container LinuxEnd of life, two years after Red Hat bought CoreOS. Apache-2.0 throughoutFedora CoreOS is the successorFlatcar, forked in 2018, CNCF incubating since 2024. Stable 4757.2.0 this month
2020-11-16GraylogTo SSPL with 4.0Free to self-hostNone
2020-12-08CentOS Linux“CentOS Linux 8, as a rebuild of RHEL 8, will end at the end of 2021.” Stream takes its place, “serving as the upstream (development) branch”The no-cost RHEL is the developer subscription, 16 systemsRocky Linux, GA June 2021, 10.2 in May 2026. AlmaLinux, stable March 2021, 10.2 in May 2026
2020-12-08Mapbox GL JSBSD-3 to Mapbox terms with v2.0.0“a billable map load occurs whenever a Map object is initialized”MapLibre GL JS, from v1.13. 6.11.1 today
2021-01-14Elasticsearch, KibanaApache-2.0 to SSPL and Elastic LicenseFree to self-host. AGPL added back in 2024OpenSearch, under the Linux Foundation since 2024. 3.8.0 in August 2026
2021-04-21Grafana, Loki, TempoApache-2.0 to AGPLv3Still open source. In the table to show where the line isNone needed
2021-08-31Docker DesktopSubscription above 250 employees or 10M USD revenueFree below the line. The threshold still standsNot a fork question. Podman Desktop and Rancher Desktop
2021-09-27AirbyteCore from MIT to Elastic License 2.0Free to run, no hosted service. Connectors stay MIT
2022-09-07AkkaApache-2.0 to BSL, free under 25M USD revenueFree below the line, converts after three yearsApache Pekko, from 2.6.20
2022-10-24GiteaGitea Ltd takes the trademark and domainsLicence unchanged, MITForgejo, under Codeberg e.V. Hard fork since 2024, GPLv3+ since v9. 16.0.5 this month
2023-06-21RHEL source“CentOS Stream will now be the sole repository for public RHEL-related source code releases.” Customers keep source through the portalUnchanged for customers. Rebuilders lose the 1:1 inputAlmaLinux dropped 1:1 for ABI compatibility. CIQ, Oracle and SUSE founded OpenELA
2023-08-10Terraform, VaultMPL-2.0 to BSL, converts to MPL-2.0 four years after each releaseFree to self-host unless you sell a competing hosted product. Vault Community Edition was not discontinuedOpenTofu, LF, 1.12.6 in August 2026. OpenBao, LF, 2.6.3 today
2023-12-11VMware, by BroadcomPerpetual licences end of sale, nineteen days after the acquisition closed. “VMware vSphere Hypervisor (free edition)” on the listSubscription only, VCF or VVF. Support runs to the end of the contract. Free ESXi came back in April 2025, “for non-production use”No fork, there is no source. Alternatives, yes: Proxmox VE, XCP-ng, KubeVirt
2024-02-14nginxNothing. Lead developer left F5 over a security policyBSD-2, identical on both sidesfreenginx. A governance fork, in the table for the same reason as Grafana
2024-02-21Linkerd“as of 2.15, we will no longer be producing open source stable release artifacts”. CNCF graduated since 2021Edge releases stay open. Stable is Buoyant Enterprise, free under 50 employees
2024-03-20RedisBSD-3 to RSALv2 and SSPLv1Free to self-host. AGPL added back in May 2025Valkey, LF, eight days later. 9.1.2 in August 2026
2024-04-09Camunda 8Camunda License 1.0 from 8.6, “Free for Development only. License needed for production use”Non-production onlyNone
2024-08-22Sourcegraph“Sourcegraph transitioned to a private monorepo.” Was Apache-2.0A read-only snapshot, archived September 2024Nothing left to fork
2024-11-07PuppetBinaries to “a private, hardened, and controlled location”, EULA25 nodes free. Source stays Apache-2.0OpenVox, Vox Pupuli, “a drop-in replacement”. 8.29.0 this month
2024-11-18CockroachDBCore retired. Enterprise free under 10M USD revenueThe free edition is gone. The free licence is a revenue testNone
2024-12-18ScyllaDB“ScyllaDB OSS AGPL 6.2 will stand as the final OSS AGPL release”. Source-available from 2025.1Free tier capped at 10 TB and 50 vCPUs
2025-05-24MinIOConsole reduced to an object browser, LDAP and OIDC login moved to the paid productAGPLv3, unchanged. See belowNone
2025-07-16BitnamiBroadcom again, twenty months after VMware. Free catalogue cut to “the most recent ’latest’ tags of the limited community-tier subset”, the rest to a legacy repository with “no further updates”Source stays Apache-2.0 on GitHubNot a fork question. Build your own images
2025-10-15MinIO“distributed as source code only”, no binaries, no imagesLast release the same day, a CVE fixNone
2025-12-03MinIO“under maintenance and is not accepting new changes”Security fixes “case-by-case”None
2026-04-25MinIORepository archived. “THIS REPOSITORY IS NO LONGER MAINTAINED”AIStor Free, a licence key, or AIStor EnterpriseNone
2026-09-11PortainerNo CE build of 3.x. 2.45 LTS is the last 2.x releasezlib, unchanged. Supported until May 2027. 3 Nodes Free for 3.xNone as of today

Reading them in one sitting, three different kinds of event fell out, and the advice is different for each.

Relicensing is the one everyone argues about. The code stays public, the licence on new releases changes. What people forget in the first week of outrage is that old releases keep their old licence forever. The binary you’re running tonight is fine. Your upgrade path is what changed. MongoDB, Elastic, Redis, HashiCorp, Sentry and Akka all did this.

Edition freeze is quieter, and I think it’s the more dangerous one. The licence doesn’t move at all. The free edition just stops getting the product’s future. Portainer did this. CockroachDB did it in 2024, when it retired Core and replaced it with a free Enterprise licence for companies under 10 million dollars in revenue. Red Hat did it twice. December 2020, the free rebuild of RHEL stopped and an upstream development branch took over the CentOS name. June 2023, the public source that Rocky and Alma rebuilt from went behind the customer portal. Not one licence changed in either move. The GPL never came into it. Chef did it in 2019, source stays Apache-2.0 and the binaries go behind a EULA, and Puppet did the same in 2025. Both got a community rebuild. And MinIO did it in a way I’ll get to.

Product going paid is the third. Docker Desktop in 2021, where the engine stayed Apache-2.0 and the desktop app grew a subscription above 250 employees or 10 million dollars. And VMware in December 2023, which is the same thing at a scale that ends careers. Nineteen days after Broadcom closed the acquisition, perpetual licences went end of sale, the free hypervisor with them, and everything became a subscription to one of two bundles. There’s no fork, because there was never any source. There are alternatives, Proxmox VE, XCP-ng, or KubeVirt inside a cluster you already run, and every one of them means migrating every VM rather than swapping a binary underneath. Most of my clients live in this row. It’s also the row that convinced me the licence is a distraction. VMware was never open, and the risk was there all the same.

Two rows are in the table to keep me honest. Grafana Labs moved Grafana, Loki and Tempo to the AGPL in 2021, and the AGPL is an OSI-approved licence. That’s open source, full stop. If I called it the same thing as SSPL, anyone who’s read both licences would stop reading, and they’d be right to. nginx in 2024 was a governance fight. The LICENSE files on nginx.org and freenginx.org are byte for byte identical. A table that only shows the scary moves is a table you shouldn’t trust.

The MinIO row

This one hurts, because it was in my cluster. For four months this year MinIO held Loki’s chunks, the Postgres backups and Longhorn’s backup target. And its free edition died without a single licence event. AGPLv3 in the first release, AGPLv3 in the last.

Watch the dates. May 2025, a release tagged “Breaking Release” cuts the embedded console down to an object browser and moves LDAP and OIDC login to the paid product. October 2025, the README says “distributed as source code only”, and an issue asking for the Docker image is closed as “working as intended”. December 2025, “under maintenance and is not accepting new changes”. April 2026, repository archived.

Four steps in eleven months, and the licence page never changed. If your register only watches the licence field, MinIO walks straight past it.

What any of these costs

Doesn’t matter which kind. The bill has the same four lines.

  1. The free edition keeps working and stops growing. Fine next year. Then Kubernetes drops an API version and it doesn’t follow.
  2. Your upgrade path now has an invoice, a revenue test or a node cap attached. All three are in the table.
  3. If there’s a fork, moving to it is a migration. The data format matches on day one and drifts from there.
  4. There’s only a fork if the project was big enough to attract one. Portainer has none as I write this. MinIO has none. Small projects don’t get an OpenBao.

What a foundation actually buys you

I expected this section to be short. The forks did better than the outrage of 2023 predicted.

OpenTofu forked Terraform fifteen days after the announcement, joined the Linux Foundation on 20 September 2023, went GA in January 2024, and shipped 1.12.6 in August 2026. OpenBao went GA in July 2024 and released 2.6.3 the day I’m writing this, with Adfinis, ControlPlane, GitLab and SAP on its supporters page. Valkey forked Redis eight days after the announcement, with AWS, Google Cloud and Oracle behind it, and shipped 9.1.2 in August. OpenSearch is five years old, has its own foundation under the Linux Foundation, and shipped 3.8.0 in August too.

All four alive. And here’s the part I didn’t expect. When Elastic added the AGPL back in August 2024, and Redis did the same in May 2025, none of the forks folded. A vendor changing its mind doesn’t unwind a fork. Once it exists you’ve got a second supplier for good, and the original gets cheaper for everyone.

“Donated to a foundation” is going to be my recommendation, so I wanted to know what it actually buys. I read the CNCF charter, updated June 2025, and the graduation template. Here’s what’s guaranteed.

  • The trademark moves to the Linux Foundation, section 11(a)(i). A company that walks away can’t take the name. OpenTofu, OpenBao and Valkey all lacked this on day one, and each had to pick a new name and start marketing from zero.
  • OSI-approved licences only, Apache-2.0 outbound, sections 11(a)(ii) and 11(b)(iii). A move to BSL or SSPL would need the Governing Board to grant an exception. Not impossible, but not one company’s call.
  • Graduation needs maintainers from at least two organisations, with an org-balance mechanism so that “no single organization controls governance decisions”.

And here’s what isn’t guaranteed, which nobody mentions when they say “it’s a CNCF project”:

  • That anyone keeps paying the maintainers. No clause obliges a company to fund anything.
  • That the maintainer company doesn’t sell a commercial derivative right next to it.
  • That the project stays alive at all. Section 6(a)(iii) lets the TOC archive it.
  • That an incubating project has more than one organisation behind it. That test only comes at graduation.

That list isn’t theoretical. Linkerd graduated in July 2021. In February 2024 Buoyant wrote “as of 2.15, we will no longer be producing open source stable release artifacts” and put stable builds behind Buoyant Enterprise, free below 50 employees. Licence untouched. Governance untouched. Graduated status untouched. The charter had nothing to say about it, because it never promised binaries.

I checked the four CNCF projects my own cluster leans on hardest. Argo graduated in December 2022, Cilium in October 2023, Kyverno in March 2026. Longhorn has been incubating since November 2021 and hasn’t graduated, which means SUSE can still be the only organisation with maintainers. I run Longhorn. It gets a lower score than Cilium in my register, and I’m fine with that, as long as the score is written down and not just felt.

Loki and Tempo get the same note. AGPL, so open source. Single vendor, so not a foundation. The exposure there is question three at the end, who pays the maintainers, rather than the licence. I run Loki too.

And Forgejo, the git forge this whole cluster deploys from, is a fork itself. Gitea Ltd took the trademark and domains in October 2022, Forgejo started two months later under Codeberg e.V., went hard fork in February 2024, and moved from MIT to GPLv3+ with v9. So the fork I picked has done a licence change of its own, in the direction I happen to like. Question one applies to it all the same.

My own cluster, from the git log

This is where I stop pointing at other people’s tables.

Three years after HashiCorp’s announcement, my cluster runs hashicorp/vault:2.1. Renovate bumped it from 1.21 to 2 on 13 August and to 2.1 on 15 September, and I merged both without a second thought. The chart comes from helm.releases.hashicorp.com. The LICENSE file in that repository now names IBM as licensor, since the acquisition closed in February 2025. I put Vault into this cluster on 5 April 2026, when OpenBao was a year past its first stable release.

Do I have reasons? Sure. It was the chart I knew. None of them was a register entry, and I’ve been recommending open source to clients the whole time, which is a little embarrassing to type out.

So why is it still Vault? Partly because Vault works, and the BSL says in so many words that internal hosting is “not considered a competitive offering”, so a home lab is exactly the user the licence leaves alone. Mostly because I’d never counted what leaving would cost. So I did, from the repository rather than from a whiteboard.

  • The chart. OpenBao ships its own. The values don’t map one to one, and mine has six months of small decisions in it, the telemetry stanza among them.
  • Three CronJobs that use the Vault image. Auto-unseal, the nightly raft snapshot, and the nightly export that walks the whole KV tree and encrypts it to an age key. Each one calls vault. On the other side the CLI is bao, which reads BAO_ADDR first and falls back to VAULT_ADDR.
  • A ClusterSecretStore called vault-backend. Every ExternalSecret in the cluster points at it. That name is the one piece of luck here, because nothing downstream changes if the store behind the name does.
  • An alert group on vault_core_unsealed and vault_autopilot_failure_tolerance, plus 1072 vault_* series in Prometheus. OpenBao kept the vault prefix on its metrics but moved the service registration labels from vault to openbao. The chart’s Services select on those labels. So did my scrape config, until I pointed it at the headless Service. Small stuff, and small stuff is what empties a dashboard.
  • The data. This is the cost that grew while I waited. OpenBao’s migration guide is an in-place node swap, with a warning box: “This guide was only tested against Vault 1.14.1. Newer versions are untested and unsupported: OpenBao makes no guarantees about storage compatibility with Vault.” I’m on 2.1, Vault doesn’t do downgrades, so there’s no way back to 1.14.1. The migration isn’t a swap anymore. It’s my disaster recovery export, replayed into an empty OpenBao with bao kv put, plus every policy, lease and auth mount rebuilt by hand.
  • A document called 09-secrets-vault.md, and six months of typing vault kv put.

Add it up and it’s a week of evenings, with a rollback plan for the one step that touches data. Vault for beginners on this blog still says Vault, and it’ll keep saying that until the migration’s done, because I’m not going to describe a lab I don’t run.

And why hasn’t it happened yet? Paid work comes first. In my lab this row bothers nobody but me. At clients the same row, with VMware or Red Hat in it, costs serious money, and those clients know I’ve been talking about open source for years, so they’re queued up waiting for my time. My own migration is behind them in that queue. Vault keeps answering requests in the meantime, and no risk register I’ve ever seen has “a week of evenings” as a budget line.

The one I did do

MinIO is the migration I did get done. It’s also the one time the register worked, even though it only existed in my head.

I added MinIO on 5 April 2026, on a 250 GiB Longhorn volume. The community repository had been in maintenance mode since December and was archived on 25 April, twenty days after my commit. I have the commit date to prove it. It installed, it ran, it would’ve kept running for years. But I knew MinIO had gone vague about its source and its licence, and that’s why I was already looking around. Otherwise August would’ve replaced MinIO with a newer MinIO.

Storage set the month. Longhorn was replicating the volume twice, MinIO wanted to replicate on top of that, and the pool was full. I didn’t want Ceph in a home lab, that’s overkill. Garage replicates itself onto a plain disk per node, so Garage it was. Five consumers moved one at a time, Loki’s chunks, the Postgres backups, Longhorn’s backup target, the Vault export, Forgejo’s storage, with MinIO kept running until its request counter read zero for half an hour. Then it went, on 11 August, and the snapshot chain under that volume handed back 470 GiB. Nearly twice what the volume claimed.

Two things broke, both in the cleanup. I tried to cut one field out of a KV secret with sed on the JSON response and wrote the whole API response back as the secret, request id and lease metadata included. vault kv rollback -version=3 saved me. Then I removed the OIDC client from one of two copies of the Keycloak realm and missed the second, which would’ve quietly stopped syncing within the hour. Neither mistake had anything to do with MinIO. Both had to do with doing a migration by hand on a weekday evening. That, more than any licence text, is what every row in that table costs.

Portainer, the row this post started with, is the one I don’t have. The Docker host that runs my household apps, Nextcloud and a Minecraft server among them, is compose files and a shell. That announcement cost me nothing, and I did nothing to earn that. Write it down anyway. The next announcement will be about something you did install.

Five questions per component

The way out is smaller than the table makes it look. Five questions per component, an afternoon’s work, and the answers go in the register with a date on them.

  1. Who owns the copyright, and is there a CLA ? A CLA hands the company the right to relicense tomorrow. A DCO , which the kernel and the CNCF use, leaves the copyright with each contributor, so a relicensing needs every one of them to agree.
  2. Who owns the trademark? If a foundation does, a fork keeps the name and the search results. If the company does, the fork starts as a stranger.
  3. Who pays the maintainers, and how do they make money? Nearly every relicensing in the table came from a single vendor whose revenue depends on a hosted or supported version of the same code, and whose announcement names someone else selling it. You can read that on the pricing page years before the blog post.
  4. Could a fork or an alternative start from where you are? Is the data format documented, and does something else read it today? For Vault, a raft snapshot worked until 1.14 and now it’s the KV export. For Portainer, the stacks are compose files. For MinIO, mc mirror to anything that speaks S3.
  5. Has the vendor done this before? Sentry twice, CockroachDB twice, Red Hat twice, Broadcom twice, Redis three times if you count the modules in 2018, MinIO four times in eleven months. Elastic and Redis did it once and came halfway back. A vendor that’s done it once has shown you the procedure.

Then decide per kind. Vault-shaped: price the exit and put a date on it, because the gap grows every month. MinIO-shaped: keep the data in a format the alternative reads and the decision can wait, because a frozen S3 server is still an S3 server. Portainer-shaped: take the free key and get on with your day.

Self-hosting only moves this risk. On a managed service the vendor’s business model changes your bill. On your own hardware it changes your upgrade path. A frozen edition keeps running on your hardware and a discontinued managed service doesn’t, and that difference is the sovereignty argument one layer down. You own the binary that runs tonight and the data in it. Next year’s release was always going to belong to whoever sets the vendor’s revenue target.

Nobody in that table did anything wrong. Companies with payroll changed the terms they were allowed to change, said so politely, and kept supporting what they’d shipped. I read Portainer’s post on a Monday and shrugged, and the shrug was the problem, because I’d never written the row down.

The Vault row is in the register now, dated 23 September 2026. OpenBao is on the list. Behind the clients. Sorry, lab.