License decisions
This file gives a recommendation for each license that the matrix does not give, the decision of a maintainer when there is one, and the causes of NOASSERTION. A license that [licenses] of core/setups/nixos/license-allowlist.toml does not have makes the report fail. The data comes from the license reports of the 28 nodes of core.
This is not legal advice. The authors are not lawyers. A person with legal knowledge must approve a decision before it goes into [licenses].
Relations between components
The compatibility of two licenses is a question only when the two works become one work. The EUPL-1.2 leaves this to the law: "This Licence does not define the extent of modification or dependence on the Original Work required in order to classify a work as a Derivative Work" (Article 1). There are three relations:
- Aggregation: separate programs on one system, for example
nginxand the api. Each program keeps its own license. A node is mostly an aggregation. For aggregation, a license only has to permit the distribution of the component. The licenses of two components do not have to be compatible with each other. - Dynamic linking: a program loads a shared library when it runs, for example a C program and
libssl.so, or a Python program and a module that it imports. The European Commission says that this does not make a derivative work: "static and dynamic linking can be implemented with other programs without barriers or conditions. On this specific point, EUPL works like the LGPL" (EUPL FAQ), with recitals 10 and 15 of Directive 2009/24/EC as the reason. The FSF has a different opinion for the GPL. There is no case law. - Static linking and incorporation: the code of the library is copied into the program, for example a Go or Rust binary with its modules and crates, or a JavaScript bundle. This is the relation that most likely makes a derivative work.
nixpkgs links C and C++ programs dynamically: each program finds its libraries in the store through its RPATH. No node uses pkgsStatic, and no node has a Haskell program. Static linking occurs in these cases:
- Go programs include their modules (for example
openbao,forgejo,incus,spire,authelia,restic,rclone,grafana). cgo linksglibcdynamically. - Rust programs include their crates (for example
garage,lldap,windmill,uv). - JavaScript applications include bundles of npm packages (for example
mastodon,peertube,grafana,forgejo,garage-webui, andasyncapi-docsof this repository).
The SBOM gives each of these programs as one component. It also gives the npm packages from the package.json files in the node_modules directories of the closure, and the crates from the Cargo.toml files in the vendor directories (cargoDeps) of the Rust packages of the roots in sbom.nix. It does not give the Go modules or the npm packages in a bundle. See "The dependencies that Go, Rust and npm builds vendor". Except for asyncapi-docs, these programs do not include code of this repository: their upstream projects combined the code, and the node only aggregates the programs.
The EUPL compatibility matrix
The matrix of the European Commission ("Matrix of EUPL compatible open source licences", July 2011, updated 2013 and 2017) has the columns "Incorporation", "Static link" and "Dynamic link". It is about inbound compatibility: "it allows you to merge a work covered by another F/OSS license into a larger work that you may distribute under the EUPL". The "Dynamic link" column is "OK" for each license of the matrix. "NO" and "?" occur only in the other columns, for example for the GPL ("NO (exceptions exist)" for incorporation). The reason that the matrix gives: "linking two programs does not produce a single derivative of both (each program stay covered by its primary licence)".
The Appendix of the EUPL-1.2 is a different list: it gives the licenses under which a licensee can distribute a work that combines an EUPL work with a work under that license (Article 5). It is an outbound list, not a list of the licenses that a dependency can have, thus the allowlist does not use it as a source. For a license that is not in the matrix, the allowlist uses the EUPL FAQ of the European Commission: "the simple fact of "Using" a covered component as a dependency or as a tool, does not transform your work in a derivative". Such a license is acceptable when it permits the distribution of the component.
Thus no license in the report fails because of dynamic linking. For aggregation and dynamic linking, a license is acceptable when it permits the distribution of the component, also for a commercial service.
Recommendations
"Nodes" is the number of nodes (of 30) with the license. "Accept" means: add the license to [licenses]. "Accepted" means: a maintainer accepted the license, and it is in [licenses] with its source. "Refuse" means: remove the component from the nodes. "Refused" means: a maintainer refused the license, it is in no list, and no node has a component with it. The report fails when a node has such a component.
Permissive licenses
These licenses permit distribution with notice and attribution conditions. They are acceptable for aggregation and for dynamic linking.
| License | Nodes | Components (examples) | Recommendation | Reason |
|---|---|---|---|---|
0BSD |
30 | libressl, git-pages, sord |
accepted | permits all use, no conditions |
MIT-0 |
30 | systemd, cffi |
accepted | MIT without the notice condition |
MIT-open-group |
30 | libx11, libice, libxau |
accepted | MIT variant |
MIT-CMU |
1 | pillow |
accepted | MIT variant |
X11 |
30 | libx11, libxcb, libpciaccess |
accepted | MIT with a no-endorsement clause |
X11-no-permit-persons |
1 | libxinerama |
accepted | X11 variant |
HPND |
30 | libx11, pngquant |
accepted | permits use, copy and distribution with notice |
HPND-sell-variant |
30 | libx11, libxfixes |
accepted | HPND variant |
HPND-doc |
30 | libx11, libxext |
accepted | HPND variant for documentation |
HPND-doc-sell |
30 | libx11, libxext |
accepted | HPND variant for documentation |
HPND with different disclaimer |
1 | xorgproto |
accepted | HPND variant |
TekHVC |
30 | libx11 |
accepted | permissive, with naming conditions; it grants no patent license |
ICU |
1 | xorgproto |
accepted | MIT variant |
Unicode-3.0 |
30 | icu4c |
accepted | permissive data and code license |
SGI-B-2.0 |
1 | xorgproto |
accepted | permissive, with notice |
Cronyx |
1 | xkeyboard-config |
accepted | "may be used, modified, copied, distributed, and sold" |
hyphen-bulgarian |
1 | xkeyboard-config |
accepted | permissive, as Cronyx |
OpenSSL |
30 | libressl |
accepted | BSD-style, with an advertising clause (attribution only) |
LicenseRef-nixos-bsdAskToEndorse |
30 | sudo |
accepted | BSD with a no-endorsement clause |
BSD |
1 | sysexits |
accepted | "BSD (all versions)" is "OK" in the matrix |
2-clause BSDL |
1 | unf |
accepted | BSD-2-Clause, which is in the matrix |
BSD-2-Clause-Patent |
5 | libvmaf |
accepted | BSD-2-Clause with an express patent grant |
Boehm-GC |
30 | boehm-gc |
accepted | permissive, with notice |
bzip2-1.0.6 |
30 | bzip2 |
accepted | BSD-style |
curl |
30 | curl |
accepted | MIT variant |
libpng-2.0 |
30 | libpng-apng |
accepted | zlib-style; "Zlib/libpng" is in the matrix |
libtiff |
5 | libtiff |
accepted | permissive, with notice |
IJG |
5 | libjpeg-turbo |
accepted | permissive; the documentation must give credit |
TCL |
1 | tcl |
accepted | BSD-style |
OLDAP-2.8 |
5 | openldap |
accepted | BSD-style |
CNRI-Python |
1 | regex |
accepted | permissive, FSF free, as Python-2.0 in the matrix |
Beerware |
30 | libbsd, libmd |
accepted | permits all use, with notice |
WTFPL |
4 | libcaca, zimg |
accepted | permits all use |
blessing |
30 | sqlite |
accepted | a public domain dedication |
Unlicense |
1 | rdf, json-ld |
accepted | a public domain dedication |
CC0-1.0 |
30 | systemd, libargon2, libblake3 |
accepted | a public domain dedication |
Public Domain |
30 | systemd, libressl, tzdata, docutils |
accepted | no copyright license is necessary |
LicenseRef-nixos-publicDomain |
30 | util-linux, hdrhistogram_c |
accepted | as Public Domain |
Weak copyleft licenses
These licenses have conditions only for changes to the component itself. The node does not change these components.
| License | Nodes | Components (examples) | Recommendation | Reason |
|---|---|---|---|---|
LGPL-2.0 |
4 | aalib, gobject-introspection, lame, libiscsi |
accepted | section 3 permits the GPL-2.0 or later instead, which is in the matrix |
MPL-1.0 |
3 | cairo |
accepted | section 6.2 permits later versions; MPL-1.1 is in the matrix |
CECILL-C |
1 | openfec (hypervisor-incus) |
accepted | FSF free, "somewhat like the GNU Lesser General Public License"; not in the matrix, thus the acceptance rests on the EUPL FAQ of the EC |
PHP-3.01 |
1 | php-with-extensions (operator-pixelfed) |
accepted | clause 5 permits later versions; "PHP License 3.0" is in the matrix |
Licenses with a choice
| License | Nodes | Components (examples) | Recommendation | Reason |
|---|---|---|---|---|
Ruby |
1 | 40 gems of operator-mastodon |
accepted | the COPYING of Ruby permits the 2-clause BSDL instead |
Artistic-1.0 |
30 | perl |
accepted | alone only for perl, which has the Perl terms (Artistic-1.0 or GPL-1.0-or-later). The FSF says to avoid it "except as part of the disjunctive license of Perl". The matrix gives "Artistic license (Perl foundation)" only as version 2.0 |
Artistic-1.0-Perl |
1 | diff-lcs (operator-mastodon) |
accepted | the gem gives a choice of MIT, Artistic-1.0-Perl and GPL-2.0-or-later, but the report joins the gemspec list with AND; see the questions |
Documentation and content licenses
| License | Nodes | Components (examples) | Recommendation | Reason |
|---|---|---|---|---|
CC-BY-4.0 |
30 | libuv (documentation) |
accepted | permits distribution with attribution |
GFDL-1.3-or-later |
4 | flac (documentation) |
accepted | permits distribution of verbatim copies |
Licenses of vendored components
These licenses come from the npm packages, the crates and the Go modules that the SBOM gives as vendored components (FR-010). A license that is "accepted" is in [licenses], with its source. For a module that is in [components], the licenses that only the module has are in no list. The Go rows come from a scan of 19 Go packages of the pinned nixpkgs that the configuration uses (see below), not from the reports of the nodes.
| License | Components (examples) | Recommendation | Reason |
|---|---|---|---|
Unicode-DFS-2016 |
crates unicode-ident, unicode_names2 |
accepted | permissive data and code license, as Unicode-3.0 |
BlueOak-1.0.0 |
npm glob, lru-cache, isexe; crate minicbor |
accepted | permissive, with a patent license |
Libpng |
crate libpng-sys (pngquant) |
accepted | zlib-style; "Zlib/libpng" is in the matrix |
Artistic-2.0 |
npm npm; crates notify, file-id |
accepted (matrix) |
the matrix gives "Artistic license (Perl foundation)", version 2.0 |
CC-BY-3.0 |
npm spdx-exceptions (data) |
accepted | permits distribution with attribution, as CC-BY-4.0 |
CDLA-Permissive-2.0 |
crates webpki-roots, webpki-root-certs (CA certificates) |
accepted | a permissive license for data; the condition is to keep the license text |
Apache 2.0 |
npm qrcode-terminal (in npm) |
[components] gives the module |
a name, not the SPDX identifier Apache-2.0. The LICENSE of the package is Apache-2.0, and the code in vendor/QRCode has MIT |
UPL-1.0 |
Go github.com/oracle/oci-go-sdk (rclone), github.com/nrdcg/oci-go-sdk (lego) |
accepted (faq) |
permissive, with a patent license. The module gives a choice of UPL-1.0 or Apache-2.0, but the classifier joins them with AND |
X11-Lucent |
Go bazil.org/fuse (rclone), github.com/anacrolix/fuse (restic) |
accepted (faq) |
permissive; a notice for the code from Plan 9, next to BSD-3-Clause |
FSFAP |
Go github.com/apache/thrift (grafana, otelcol, otelcol-contrib) |
accepted (faq) |
all-permissive; only for some autoconf macros in the source, next to Apache-2.0 |
CC-BY-SA-4.0 |
Go github.com/opencontainers/go-digest (forgejo, forgejo-runner, incus, openbao, opentofu, otelcol, otelcol-contrib, spire) |
[components] gives the module |
only for the documentation (LICENSE.docs), which the programs do not include. The code has Apache-2.0 |
TPM-2 |
Go github.com/google/go-tpm-tools (spire) |
accepted (faq) |
permissive; the conditions are for the patents of the TCG members. Only for the TPM 2.0 simulator of Microsoft in the module (simulator/ms-tpm-20-ref), next to Apache-2.0 |
AFL-2.0, AFL-2.1, BSD-2-Clause-NetBSD, BSD-3-Clause-Clear, BSD-4-Clause-UC, BSD-Source-Code, CC-BY-SA-2.0, GPL-1.0, GPL-3.0-with-bison-exception, InnerNet, LicenseRef-C-Ares, LicenseRef-MIT-Lucent, LicenseRef-uthash, OSL-1.1, OpenLDAP, OpenVision, RSA, Rijndael-3.0, Spencer-86, SunPro |
Go github.com/hashicorp/vic (openbao) |
[components] gives the module |
only in the list of third-party licenses of the vSphere Integrated Containers product, in the LICENSE of the module. The list says that the product does not necessarily use all of them. The module has Apache-2.0 |
Licenses that need a person
| License | Nodes | Components (examples) | Recommendation | Reason |
|---|---|---|---|---|
Brakeman Public Use License |
1 | brakeman (operator-mastodon) |
refused | "Commercial Uses ... require a commercial, non-free license", and this includes a hosted service. brakeman is in the development group of the Gemfile of Mastodon. The bundlerEnv of mastodon in nixpkgs gives no groups and thus includes all groups. nix/overlays/mastodon.nix gives the groups without development and test, and sets BUNDLE_WITHOUT for the asset build. The node sets BUNDLE_WITHOUT for its units |
FDK-AAC |
1 | fdk-aac (hypervisor-incus, through qemu_kvm of the Incus module) |
refused | it grants no patent license; Debian gives it in non-free and Fedora does not allow it. It comes through the SDL display (sdl2-compat, sdl3, zenity, gtk4, gst-plugins-bad) and the PipeWire audio of qemu. Incus does not use these. core/components/hosting-provider/incus/qemu.nix loads the Incus module with a qemu_kvm that has sdlSupport, gtkSupport and pipewireSupport set to false |
Alliance for Open Media Patent License 1.0 |
4 | svt-av1 |
accepted (faq) |
a royalty-free patent grant in addition to the copyright license (BSD-3-Clause), with defensive termination |
LicenseRef-nixos-free |
28 | dejavu-fonts-minimal, gd, gfxstream, poppler-data |
[components] gives the packages |
nixpkgs does not name the license. The license files of the sources give the Bitstream Vera and Arev Fonts licenses (dejavu-fonts-minimal), GD (gd), Apache-2.0, MIT, CC-BY-4.0 and the M+ Font License (gfxstream), and a BSD license, GPL-2.0-only or GPL-3.0-only, and an MIT-style license (poppler-data) |
OML |
6 | FCGI |
[components] gives the package |
the LICENSE of the Perl module permits use, changes and distribution for any purpose, with the copyright notices and the license text |
CFITSIO |
1 | cfitsio (operator-mastodon) |
[components] gives the package |
licenses/License.txt of the library permits use, changes and distribution, with the copyright notice and the disclaimer |
NOASSERTION |
1 | github.com/tuvistavie/securerandom (hosting-provider-postgresql, through pgweb) |
refused | the module has no license file, no file header and no license statement in its README.md, thus nothing permits its distribution. nix/overlays/pgweb.nix removes the module from pgweb. A decision applies to each component, not to the identifier |
NOASSERTION |
1 | simple-dark-gray-bootloader (dev-fediversity-ci, the default splashImage of GRUB) |
refused | nixos-artwork has no license file, and nixpkgs says "license not clarified". boot.loader.grub.splashImage = null removes the image from the node |
Components without license data
A component has NOASSERTION when bombon did not find its derivation. bombon finds the derivations only through derivation values (drvAttrs), and a NixOS system gets most packages through strings. sbom.nix gives bombon more roots (see FR-002 of the license report specification): it finds the package of each .drv file of the build of the toplevel from its name, and it adds system.extraDependencies. A unit that has a package of this repository only in a string adds the package to system.extraDependencies, for example the LLDAP provider of lldap-provision. The scripts that the configuration generates, for example forgejo-runner-daemon-* and gitea-register-runner-*, get the license of this repository (FR-009 of spec.md). partLicenses in sbom.nix gives the licenses of a package to the parts of the package (FR-011 of spec.md). With these roots and these rules, the SBOMs of the 28 nodes have 24 component names without license data. [components] has 22 of them. The other two are github.com/tuvistavie/securerandom and simple-dark-gray-bootloader: their verdict is unknown, thus the reports of hosting-provider-postgresql and dev-fediversity-ci fail. The causes:
| Cause | Components | Fix |
|---|---|---|
The initrd, which is not a root (see sbom.nix) |
initrd-linux (all nodes) |
a row in [components], until upstream (bombon) has a purl for each output and keeps a root without a version |
The D-Bus configuration of makeDBusConf, which has no meta |
dbus 1 (all nodes) |
partLicenses, until upstream (nixpkgs) gives meta to makeDBusConf |
| Go modules without a license file in the root directory of the module | github.com/gogo/googleapis (spire), github.com/yeqown/reedsolomon (openbao), bitbucket.org/atlassian/go-asap/v2 (opentelemetry-collector), github.com/rootless-containers/proto/go-proto (incus) |
a row in [components] after a person examined the source of the module |
| A Go module without a license | github.com/tuvistavie/securerandom (pgweb) |
a decision of a maintainer (see the table above). It has no row in [components] |
| A background image without a license | simple-dark-gray-bootloader (dev-fediversity-ci) |
a decision of a maintainer (see the table above) |
A crate without a license in its Cargo.toml |
kuska-handshake (garage) |
a row in [components] after a person examined the source of the crate |
An npm package without a license in its package.json |
readline-browserify (redis-commander) |
a row in [components] after a person examined the source of the package |
Ruby gems of a bundlerEnv without a gemspec license |
webpush, validate_url, omniauth-cas, idn-ruby, swd of operator-mastodon |
a row in [components], until upstream changes: bundix and the gemsets of nixpkgs do not keep the licenses (NixOS/nixpkgs#576545, nix-community/bundix#124) |
Parts of the Mastodon package without meta |
mastodon-gems-<version>, mastodon-modules of operator-mastodon |
partLicenses, until upstream (nixpkgs) gives the meta of mastodon to these derivations |
The PHP of the Pixelfed module of nixpkgs, which the module keeps in a let |
php-with-extensions, php-extra-init of operator-pixelfed |
partLicenses, until upstream (nixpkgs) gives the PHP package of the module as an option value |
The meta.license of perl in nixpkgs gives only one of its licenses (artistic1, upstream Artistic-1.0 or GPL-1.0-or-later). Upstream (nixpkgs) can give [ artistic1 gpl1Plus ]. Artistic-1.0 is in [licenses].
The dependencies that Go, Rust and npm builds vendor
The report must check the modules, crates and npm packages that the Go, Rust and JavaScript programs include. These programs do not include code of this repository, thus they are an aggregation. But the node distributes them, thus their notice conditions apply. sbom-vendored.py adds them to the SBOM (FR-010), each one with its parent packages:
- npm: the
package.jsonfiles in thenode_modulesdirectories of the closure, with their declared license. These files are in the closure, thus the build of the SBOM does not get larger. - Rust: the
Cargo.tomlfiles in the vendor directories (cargoDeps) of the Rust packages of the roots, with their declared license. The vendor directory has all the crates ofCargo.lock, also the crates for other platforms, thus the SBOM can give more crates than the build links. - Go:
sbom-go-modules.pyreads the modules that each program links from its build information (.go.buildinfo, the list ofgo version -m), and the license files from the root directory of each module in the module directory (goModules) of the package. In a vendor directory, a module that areplacedirective changes to another module is in the directory of the path that thego.modrequires, thus the script gets that directory frommodules.txt. A Go module declares no license, thusidentify_license(licenseclassifier) finds the licenses in the text, and the SBOM gives them as concluded. The scan runs in one derivation for each Go package of the roots, thus the SBOM of a node gets only a small JSON file.
These dependencies are not in the SBOM (see "Known Deviations" in the license report specification):
- The crates of a Rust package and the Go modules of a Go package that is not a root, for example
librsvg. A walk through all of thedrvAttrsof the roots finds them, but also the packages that only the build of the toplevel uses. With their vendor directories, the build of the SBOM of a node needs 1 GB to 4 GB more. - The Go modules of a Go package without a module directory (
vendorHash = null), for examplegrafana-lokiandtempo, and the Go standard library. - The npm packages in the bundles of a front end, for example
public/packsof Mastodon. A bundle has nopackage.jsonfiles.
The source of the Go data
| Source | Result |
|---|---|
A scan of goModules (chosen) |
no compilation; goModules is a fixed-output derivation that the build of the package already needs, thus a binary cache has it |
A second build of the package, for example with go-licenses |
needs goModules too, and compiles the package again |
modules.txt of goModules for the module list |
has also the modules of other platforms and build tags, and the proxyVendor layout has no modules.txt; the build information of a program has only the modules that it links |
| Classifier | Result |
|---|---|
licenseclassifier (chosen) |
7.5 MB closure; finds each license in a file with several licenses, and a license notice (-headers) |
askalono |
57 MB closure; gives only one license for a file, and no result for a file with several licenses |
licensee, go-licenses, scancode-toolkit, trivy |
a Ruby, Go or Python program with a larger closure, or a scanner that does more than the classification |
Questions
- Does a gemspec list of licenses (
spec.licenses) meanANDorOR? The documentation of RubyGems does not say. Most gems with a list give a choice, for examplediff-lcsand the gems withRubyandBSD-2-Clause. - Does a hosted service "distribute" in the sense of the licenses? The EUPL-1.2 says yes ("providing access to its essential functionalities"), and so does the AGPL. Most other licenses apply only to copies. The recommendations above take the strict position: each component is distributed.