Licensing and the DCO
This chapter is the legal and provenance foundation under every Firecracker contribution: the
Apache-2.0 license the project is distributed under, the NOTICE/THIRD-PARTY/CREDITS
attribution files it maintains, the Developer Certificate of Origin (DCO) it uses instead
of a Contributor License Agreement (CLA), the exact Signed-off-by mechanics the DCO bot
enforces, the license header that goes on source files, and the dependency-license gate
(cargo-deny / deny.toml) that keeps a bad-licensed crate out of the build. None of this is
optional and none of it is waved through for cleverness or seniority — a PR with a missing
sign-off or a GPL dependency is blocked the same way a failing test is blocked.
The throughline: Firecracker is a piece of production infrastructure distributed to the world under a permissive open-source license, and the licensing machinery exists to guarantee, mechanically and on every PR, that the project can keep distributing it cleanly. Get the licensing wrong and the problem isn't a style nit — it's a contribution that legally cannot be accepted.
cd ~/fc-src
# The authoritative artifacts this chapter explains. Read them, don't trust this page:
ls LICENSE NOTICE CONTRIBUTING.md
ls THIRD-PARTY THIRD_PARTY CREDITS deny.toml 2>/dev/null # names/locations vary — find yours
find . -maxdepth 2 -iname "third*party*" -o -iname "credits*" -o -iname "deny.toml" 2>/dev/null
# The DCO and sign-off requirement in the contribution doc (verify wording on your branch):
rg -n -i "DCO|Developer Certificate of Origin|Signed-off-by|sign-off|sign off|CLA" CONTRIBUTING.md
Why Apache-2.0
Firecracker is distributed under the Apache License 2.0, the same permissive, OSI-approved license AWS uses for most of its open-source infrastructure and the license shared by the rust-vmm crates Firecracker builds on. Apache-2.0 is the deliberate choice for a piece of software that AWS both runs as production infrastructure (Lambda, Fargate) and wants the broadest possible ecosystem to adopt and embed (Kata, firecracker-containerd, Fly.io, Vercel, and others).
What Apache-2.0 gives the project, and why it matters for you as a contributor:
| Apache-2.0 property | What it means in practice |
|---|---|
| Permissive | Anyone may use, modify, and redistribute (including commercially) without copyleft obligations — this is why an ecosystem could grow around it |
| Explicit patent grant | Contributors grant a patent license for their contributions; users get patent protection — unusually important for low-level systems code |
| Attribution preserved | Redistributors must keep LICENSE and NOTICE; this is the mechanism behind the attribution files below |
| No "viral" reach | Embedding Firecracker (or a microVM stack atop it) does not force you to open-source your own code — the reason Kata/containerd can build on it |
Note: The permissive choice is the opposite of the OpenSearch story, where the project exists precisely because a permissive license was taken away (the 2021 SSPL relicensing) and the fork reasserted Apache-2.0. Firecracker never had that fight — AWS open-sourced it under Apache-2.0 from the start and has kept it there. But the enforcement discipline is the same in both projects: the license is checked mechanically, and a dependency or a header that compromises it is an existential problem, not a cosmetic one.
The whole patent-grant point is why the project cares so much about provenance — which is exactly what the DCO certifies.
DCO, not CLA: why the difference matters
Many corporate open-source projects require a Contributor License Agreement — a separate legal document you (or your employer) sign once, often assigning or licensing broad rights to the project's owner before any contribution is accepted. Firecracker does not use a CLA. It uses the Developer Certificate of Origin instead, and the difference is worth understanding because it shapes how every commit you make must look.
| CLA | DCO (Firecracker's choice) | |
|---|---|---|
| What it is | A legal agreement signed out-of-band, often per-contributor or per-employer | A per-commit certification embedded in the commit itself |
| Friction | High: paperwork, legal review, an employer signature, a bot tracking who signed | Low: one git flag per commit |
| What you assert | Varies; sometimes a copyright assignment or a broad license grant | A narrow, standard statement: you have the right to submit this under the project's license |
| Where it lives | A separate database/agreement | The Signed-off-by: trailer in the commit message |
| The contributor cost | Sign once, but a real barrier — especially for employees needing legal sign-off | git commit -s — no separate paperwork |
The DCO is a short, fixed text (the canonical version at
developercertificate.org). When you add a Signed-off-by:
trailer to a commit, you are certifying that statement for that commit: in plain terms, that
the contribution is yours to give (you wrote it, or it was given to you under a compatible
license), and that you're submitting it under the project's open-source license.
Why Firecracker prefers it: a DCO is lighter weight for contributors (no out-of-band
paperwork, so a strong systems engineer can land a fix the same afternoon they wrote it), it
keeps the provenance attached to the commit (the certification travels with the code in
git history forever, not in a separate database), and it asks for exactly what's needed and
no more (the right to contribute under Apache-2.0, not a copyright assignment). For a project
that wants a broad contributor base while staying legally clean, the DCO is the lower-friction,
provenance-preserving choice. This is the legal substance behind the mechanics you met in
the GitHub review chapter.
The Signed-off-by mechanics
The DCO is enforced by a bot that checks every commit in a PR. The rule is binary: every
commit must carry a Signed-off-by: trailer whose name and email match the commit author,
or the bot blocks the merge. No maintainer can wave it through — it is the most impersonal gate
in the whole process.
# Set the identity you will sign with — BEFORE you start. The email must match.
git config user.name "Your Name"
git config user.email "you@example.com"
# Sign off as you commit. This appends the trailer using your git identity:
git commit -s -m "vmm: validate balloon target against guest memory size"
# The commit message now ends with:
# Signed-off-by: Your Name <you@example.com>
The trailer is the literal line Signed-off-by: Your Name <you@example.com>, and git commit -s
generates it from your configured identity — never type it by hand with a different name/email,
because the bot compares it against the author and a mismatch blocks the PR.
Fixing the common failures (you will hit at least one of these):
# Forgot to sign off the LAST commit:
git commit --amend -s --no-edit
git push --force-with-lease
# A whole branch of commits is missing sign-offs — rebase and re-sign every one:
git rebase --signoff main
git push --force-with-lease
# The sign-off email doesn't match the author email (a silent, common blocker):
git config user.email "the-address-you-signed-with@example.com"
git rebase --signoff main # re-sign with the corrected identity
git push --force-with-lease
Warning: A green-looking commit with a
Signed-off-bywhose email doesn't match the author is still a blocked PR — the bot checks the match, not just the presence of the trailer. The single most common avoidable DCO failure is an anonymized GitHub no-reply email in the commit author field that doesn't match the address you signed with. Setgit config user.emailcorrectly before your first commit and this never happens.
Tip: Wire sign-off into your habit so you never forget it:
git config alias.cs 'commit -s', or a prepare-commit-msg hook that appends the trailer.CONTRIBUTING.mdalso recommends thetools/devtool checkstyle/checkbuildhooks (code style & trust) — add the sign-off habit to the same muscle memory.
License headers on source files
Source files carry a license header so the license travels with the code even when a single file is copied out of the repo. The exact header text and the SPDX form are project conventions — read an existing file rather than inventing one, because the precise wording (and whether files inherited from crosvm carry an additional provenance line) matters.
cd ~/fc-src
# See the real header on a representative source file (don't guess — copy the live form):
sed -n '1,5p' src/vmm/src/lib.rs
sed -n '1,5p' src/firecracker/src/main.rs
# Firecracker forked originally from crosvm; some files carry crosvm/Chromium provenance.
# Confirm the header convention and any BSD-3-Clause provenance notice on inherited files:
rg -n "SPDX-License-Identifier|Copyright|Apache-2.0|crosvm|Chromium|BSD-3" src/vmm/src/lib.rs
What to get right:
- Every new source file gets the project's standard header — the SPDX
Apache-2.0identifier and the copyright line in the exact form the existing files use. - Inherited files keep their provenance. Firecracker was forked from Google's crosvm; files derived from crosvm may carry the original BSD-3-Clause copyright notice in addition to Firecracker's. Don't strip a provenance notice — preserving it is an Apache-2.0/BSD attribution obligation, not a formality.
- The header is checked. The style/checkstyle gate (
tools/devtool checkstyle) flags a file missing or mismatching the header — so a missing header fails CI, exactly like a clippy warning. Run it locally and it never surprises you.
Attribution files: NOTICE, THIRD-PARTY, CREDITS
Apache-2.0 requires that redistributors preserve attribution, and Firecracker maintains the files that carry it. The exact set and naming vary by branch — find yours — but the roles are stable:
| File | Role | Why it matters |
|---|---|---|
LICENSE | The full Apache-2.0 text | The license itself; must ship with every redistribution |
NOTICE | Required attribution notices (Apache-2.0 §4(d)) | Downstream redistributors must preserve it; dropping required content is a compliance defect |
THIRD-PARTY / THIRD_PARTY | Licenses/attributions of bundled or vendored third-party code | Records what FC ships that isn't FC's, and under what terms |
CREDITS | Acknowledgements / contributor or upstream credits | Attribution for code and ideas the project builds on (e.g. crosvm) |
cd ~/fc-src
# Find and read whichever exist on your branch:
ls LICENSE NOTICE 2>/dev/null
find . -maxdepth 2 \( -iname "third*party*" -o -iname "credits*" \) 2>/dev/null
sed -n '1,30p' NOTICE 2>/dev/null
What a contributor must get right: if you add or vendor third-party code, you must add its
license and attribution to the appropriate file, and if a dependency ships a NOTICE whose
content Apache-2.0 (or its own license) requires you to carry, that content must land in the
right place. Dropping or mangling a required attribution is a license compliance defect, not a
cosmetic one — and it's exactly the kind of thing a maintainer checks when a PR adds a
dependency.
Dependency licensing: cargo-deny and deny.toml
Because Firecracker is a Rust project that pulls a tree of crates from crates.io and the
rust-vmm org, the highest-leverage license risk is a transitive dependency with an
incompatible license sneaking in. The defense is cargo-deny, configured by a deny.toml
in the repo, run in CI (and runnable locally), which checks the entire dependency graph against
a policy.
cd ~/fc-src
# The policy file — read it to see exactly what's allowed/denied on your branch:
cat deny.toml 2>/dev/null || find . -iname deny.toml
# Run the license check across the whole dependency tree:
cargo deny check licenses
# cargo-deny also checks more than licenses (verify which the policy enables):
cargo deny check # licenses, bans, advisories (security), sources
What deny.toml typically governs (confirm the exact policy on your branch — it's the source
of truth):
cargo-deny check | What it enforces |
|---|---|
| licenses | Every crate's license is on the allowed list (Apache-2.0, MIT, BSD, ISC, etc.) and none is on the denied list (GPL/AGPL/copyleft, source-available) — across the whole transitive graph |
| bans | Specific crates/versions are banned; duplicate versions are flagged; a [bans] allow/deny list |
| advisories | Crates with known security advisories (RustSec) are flagged — supply-chain security, not just licensing |
| sources | Dependencies come only from approved registries/git sources, not arbitrary ones |
The practical rule for a contributor: adding a dependency is never just a Cargo.toml line.
When you add a crate, cargo deny check runs over the new graph; if the crate (or anything it
pulls in transitively) has a disallowed license, the build fails. You then either drop the
dependency, find a permissively-licensed alternative, or — if it's genuinely needed and its
license is acceptable but not yet allowed — propose a deny.toml change, which a maintainer
reviews as the license decision it is. A new dependency is a supply-chain and a license
decision, and the maintainers scrutinize it accordingly
(maintainer mindset).
Warning: A disallowed-license crate three levels deep in the dependency tree is just as blocking as a direct one —
cargo-denychecks the whole graph. Before adding a dependency, runcargo deny check licenseslocally and read what it pulls in. "It's only a transitive dependency" is not a defense; the build checks transitively on purpose.
What a contributor must get right (the checklist)
Run this on every PR, before you ask for review — every box is a thing the bots or a maintainer will otherwise bounce the PR on:
-
DCO sign-off on every commit (
git commit -s), with the trailer email matching the author email — DCO bot green. -
License header on every new source file, in the project's exact form
(
tools/devtool checkstyleclean); inherited/crosvm-provenance notices preserved. -
Attribution updated if you added/vendored third-party code: its license and any
required
NOTICEcontent carried in the right file (NOTICE/THIRD-PARTY/CREDITS). -
Dependency licensing clean:
cargo deny check licensespasses for the new graph; any new crate's license (and its transitive deps') is on the allowed list — or a revieweddeny.tomlchange justifies it. - No new copyleft/source-available dependency introduced directly or transitively.
-
If you touched
deny.toml, the change is explained in the PR as the license decision it is.
If every box is checked, the only licensing question left is a human one — and there usually isn't one, which is exactly the point: the machinery makes the clean Apache-2.0 property automatic on every PR.
Prove You Understand This
- Why is Firecracker Apache-2.0 rather than copyleft, and what specifically does the explicit patent grant buy a low-level systems project?
- Explain the DCO-vs-CLA choice: what does a
Signed-off-bycertify, and why does Firecracker prefer it over a CLA for both the contributor and the project? - Your PR has three commits; the DCO bot is red on one because its sign-off email doesn't match the author. Give the exact commands to fix the whole branch without losing work.
- You're adding a new file derived from crosvm and a new crate dependency. What must you get right on the header, the attribution files, and the dependency license — and which command checks the last one across the whole graph?
- A maintainer asks you to justify a
deny.tomlchange. Why is adding a dependency a license and a supply-chain decision, and what doescargo-denycheck beyond licenses? - Why is a disallowed-license crate three levels deep in the dependency tree just as blocking as a direct one?
Next: Code Style, Test Quality, and Building Trust — the everyday craft gates that, together with the licensing discipline here, earn you the review bandwidth that turns contributions into influence.