Create and update per-distro package files in release-notes/{version}/distros/ that document .NET runtime dependencies and package availability for each Linux distribution. USE FOR: setting up distros/ for a new .NET version, updating dependency package names when distro versions change, auditing package data. DO NOT USE FOR: supported-os.json changes (use update-supported-os skill), os-packages.json (legacy format).
Create and maintain per-distro JSON files in release-notes/{version}/distros/. Each file declares the native packages .NET depends on for a specific distribution, scoped to a single .NET version.
release-notes/{version}/distros/
├── dependencies.json # distro-agnostic dependency list (what .NET needs)
├── index.json # lists all per-distro file names
├── alpine.json # per-distro: dependencies with distro-specific names
├── ubuntu.json
├── fedora.json
└── ...
distros/ directory created for the first timelibicu74 → libicu76 on a new Ubuntu)The release-notes tool must be installed for markdown generation and package availability queries. The public dotnet-release tool is now for browsing release data and CVEs.
# Check if already installed
release-notes --version
If not installed:
dotnet tool install -g release-notes \
--add-source https://nuget.pkg.github.com/richlander/index.json
If already installed, update to latest:
dotnet tool update -g release-notes \
--add-source https://nuget.pkg.github.com/richlander/index.json
The user provides:
Ask the user: Do you want to update dotnet packages (which .NET packages are available in each distro)? If so, ask them to provide or set PKGS_ORG_TOKEN. This requires a pkgs.org Gold+ subscription.
Distro-agnostic list of packages .NET requires. Updated once per major release — rarely changes.
{
"channel_version": "11.0",
"packages": [
{
"id": "libc",
"name": "C Library",
"required_scenarios": ["all"],
"references": ["https://..."]
},
{
"id": "openssl",
"name": "OpenSSL",
"required_scenarios": ["https", "cryptography"],
"min_version": "1.1.1",
"references": ["https://..."]
}
]
}
Omit min_version and references when null/empty.
{
"channel_version": "11.0",
"distros": [
"alpine.json",
"azure_linux.json",
"ubuntu.json"
]
}
Alphabetically sorted list of per-distro file names.
Scoped to the .NET version of the parent directory. No dotnet_versions field — the version is the directory.
{
"name": "Ubuntu",
"install_command": "apt-get install -y {packages}",
"releases": [
{
"name": "Ubuntu 24.04 (Noble Numbat)",
"release": "24.04",
"dependencies": [
{ "id": "ca-certificates", "name": "ca-certificates" },
{ "id": "libc", "name": "libc6" },
{ "id": "libicu", "name": "libicu74" },
{ "id": "openssl", "name": "libssl3t64" }
]
}
]
}
Optional fields on each release (populated by package availability queries):
{
"dotnet_packages": [
{ "component": "sdk", "name": "dotnet-sdk-11.0" },
{ "component": "runtime", "name": "dotnet-runtime-11.0" }
],
"dotnet_packages_other": {
"backports": {
"install_command": "sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update",
"packages": [
{ "component": "sdk", "name": "dotnet-sdk-11.0" }
]
}
}
}
The install_command in dotnet_packages_other is the command to register the feed — it must be run before packages can be installed with the distro's normal install command. This field is required for every alternative feed entry. See Known alternative feed commands for values.
Use os-packages.json from the same version (if it exists) or the previous .NET version as the source for dependency data:
cat release-notes/{version}/os-packages.json
# or from a previous version:
cat release-notes/{prev-version}/os-packages.json
Also reference release-notes/{version}/supported-os.json for the list of supported Linux distributions and versions.
Extract the packages array from os-packages.json. Convert keys to snake_case:
required-scenarios → required_scenariosmin-version → min_versionThis file changes very rarely — it lists what .NET needs, not what distros call things.
For each distribution in os-packages.json:
_ (e.g. azure_linux.json, centos_stream.json)install_command: From the distro's install-commands — use the last command, format as {command-root} {command-parts}, normalize {packageName} → {packages}releases: One entry per distro release, with dependencies sorted alphabetically by iddotnet_packages or dotnet_packages_other — those are populated separatelyThe scope of distros/ is broader than supported-os.json. Include pre-release distro versions and permanent rolling channels where the package information is helpful:
These are informational — their presence does not imply official .NET support.
List all per-distro file names alphabetically.
# Verify all JSON parses
for f in release-notes/{version}/distros/*.json; do
python3 -c "import json; json.load(open('$f'))" && echo "OK: $f"
done
Confirm every Linux distro in supported-os.json has a corresponding file.
Regenerate dotnet-dependencies.md from the JSON files:
release-notes generate dotnet-dependencies {version} release-notes
This produces release-notes/{version}/dotnet-dependencies.md with copy-pasteable install commands for each distro and release. Never hand-edit this file — it is generated from the JSON.
supported-os.json for the new releasename, release, and any changed package names (e.g. libicu74 → libicu76)Delete the release object from the releases array. If the entire distro is dropped, delete the file and remove it from index.json.
Update the name field in the relevant dependency entry. Package names change between distro releases due to shared library versioning (e.g. libicu70 on Ubuntu 22.04 → libicu74 on 24.04).
This populates dotnet_packages and dotnet_packages_other in each per-distro file — recording which .NET packages (SDK, runtime, ASP.NET Core) are available in each distro's package feeds.
Requires PKGS_ORG_TOKEN to be set.
export PKGS_ORG_TOKEN=<token>
release-notes query distro-packages --dotnet-version {version} --output /tmp/distro-packages.json
This queries pkgs.org and supplemental feeds (Ubuntu backports via Launchpad, Homebrew, NixOS) and writes a JSON file with package availability per distro.
The output file has this structure:
{
"channel_version": "10.0",
"last_verified": "2026-03-25",
"distributions": [
{
"name": "Ubuntu",
"releases": [
{
"name": "Ubuntu 24.04",
"release": "24.04",
"feeds": {
"builtin": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" },
{ "component_id": "runtime", "package_name": "dotnet-runtime-10.0" },
{ "component_id": "aspnetcore-runtime", "package_name": "aspnetcore-runtime-10.0" }
],
"backports": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
]
}
}
]
}
]
}
For each distro+release in the query results, match it to the corresponding per-distro file and update:
feeds["builtin"] → dotnet_packages (flat list)feeds["backports"]) → dotnet_packages_other["backports"]Field mapping from query → per-distro file:
| Query field | Per-distro field |
|---|---|
component_id | component |
package_name | name |
Every dotnet_packages_other entry must include an install_command — the command to register that feed before packages can be installed. See Known alternative feed commands for the values to use.
Example — if the query returns this for Ubuntu 24.04:
"feeds": {
"builtin": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
],
"backports": [
{ "component_id": "sdk", "package_name": "dotnet-sdk-10.0" }
]
}
Then ubuntu.json release 24.04 becomes:
{
"name": "Ubuntu 24.04 (Noble Numbat)",
"release": "24.04",
"dependencies": [ ... ],
"dotnet_packages": [
{ "component": "sdk", "name": "dotnet-sdk-10.0" }
],
"dotnet_packages_other": {
"backports": {
"install_command": "sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update",
"packages": [
{ "component": "sdk", "name": "dotnet-sdk-10.0" }
]
}
}
}
Not all distros appear in the query results (e.g. RHEL packages are in a subscription-only repo). Leave dotnet_packages absent for those — do not add an empty list.
pkgs.org may not have data for newly released distro versions yet. When a supported distro release is missing from the query results, check the distro's own package list as a fallback.
Ubuntu — query packages.ubuntu.com for the release codename:
curl -s "https://packages.ubuntu.com/{codename}/allpackages?format=txt.gz" \
| gunzip | grep -i "dotnet.*{major}"
curl -s "https://packages.ubuntu.com/{codename}/allpackages?format=txt.gz" \
| gunzip | grep -i "aspnetcore.*{major}"
For example, to check Ubuntu 26.04 (codename resolute) for .NET 10:
curl -s "https://packages.ubuntu.com/resolute/allpackages?format=txt.gz" \
| gunzip | grep -iE "(dotnet|aspnetcore).*10"
If the packages are found (e.g. dotnet-sdk-10.0, dotnet-runtime-10.0, aspnetcore-runtime-10.0 in the universe component), add them as dotnet_packages for that release.
Fedora — query the Bodhi update system and source RPM spec:
# Check which Fedora releases have dotnet builds
curl -s "https://bodhi.fedoraproject.org/updates/?packages=dotnet{major}.{minor}&rows_per_page=20" \
| python3 -c "
import sys, json
for u in json.load(sys.stdin).get('updates', []):
print(f\"{u['release']['name']}: {u['title']} ({u['status']})\")"
For example, to check .NET 10.0:
curl -s "https://bodhi.fedoraproject.org/updates/?packages=dotnet10.0&rows_per_page=20" \
| python3 -c "
import sys, json
for u in json.load(sys.stdin).get('updates', []):
print(f\"{u['release']['name']}: {u['title']} ({u['status']})\")"
Results show each Fedora release with its build status (e.g. F44: dotnet10.0-10.0.104-1.fc44 (testing)). To confirm the subpackage names, check the spec file:
curl -s "https://src.fedoraproject.org/rpms/dotnet{major}.{minor}/blob/f{release}/f/dotnet{major}.{minor}.spec" \
| grep -E "^%package|^Name:"
Fedora packages follow a consistent naming scheme (dotnet-sdk-{major}.{minor}, dotnet-runtime-{major}.{minor}, aspnetcore-runtime-{major}.{minor}), so this is mainly a confirmation step.
Other distros — Alpine packages can be checked at pkgs.alpinelinux.org. For most other distros, pkgs.org covers them well. Only fall back to direct queries when pkgs.org is missing data for a release you expect to have packages.
Show the user a summary of which distros+releases have packages and from which feeds, and flag any gaps (supported distro but no packages found).
After any JSON changes, regenerate both markdown files:
release-notes generate dotnet-dependencies {version} release-notes
release-notes generate dotnet-packages {version} release-notes
dotnet-dependencies.md — what OS packages .NET requires (from dependency data)dotnet-packages.md — where to get .NET packages (from dotnet_packages / dotnet_packages_other data)Important: Do not hand-edit these markdown files. They are generated from the distros/ JSON files. If the output needs to change, update the generator or template in dotnet-release.
git add release-notes/{version}/distros/ release-notes/{version}/dotnet-dependencies.md release-notes/{version}/dotnet-packages.md
git commit -m "Update {version} distro packages — <summary>"
When packages come from a non-builtin feed, the install_command field tells users how to register that feed before installing packages. Use the exact commands below.
Feed name: backports
sudo add-apt-repository ppa:dotnet/backports && sudo apt-get update
This PPA provides .NET packages for older Ubuntu LTS releases that don't carry .NET in the default archive. After registering, packages are installed with the normal apt-get install command.
Feed name: microsoft
wget https://packages.microsoft.com/config/{distro}/{version}/packages-microsoft-prod.deb -O /tmp/packages-microsoft-prod.deb && sudo dpkg -i /tmp/packages-microsoft-prod.deb && rm /tmp/packages-microsoft-prod.deb
Replace {distro} and {version} with the distro name and version (e.g. ubuntu/22.04, debian/12). Note: Microsoft is phasing out PMC for Ubuntu 24.04+ — prefer the builtin or backports feed when available.
If the query returns a feed name not listed above, ask the user for the registration command. Do not guess — incorrect feed setup commands are worse than none.
release-notes/11.0/distros/ubuntu.json is about .NET 11.0 on Ubuntuid (e.g. libicu) with a distro-specific name (e.g. libicu74)dependencies.json is the "what .NET needs" list; per-distro files map those to real package nameslibicu are versioned on Debian/Ubuntu (e.g. libicu76) but not on Fedora/RHEL (just libicu)dotnet{major}-{component} (e.g. dotnet9-sdk)dotnet-sdk-{major}.{minor}, dotnet-runtime-{major}.{minor}install_command uses {packages} as a placeholder for the package listThe name fields (both top-level distro name and per-release names) must use full display names, never acronyms. These names appear in generated markdown and user-facing documentation.
| ❌ Acronym | ✅ Full display name |
|---|---|
| RHEL | Red Hat Enterprise Linux |
| SLES | SUSE Linux Enterprise Server |
Examples:
"name": "Red Hat Enterprise Linux" (not "RHEL")"name": "Red Hat Enterprise Linux 9" (not "RHEL 9")"name": "SUSE Linux Enterprise Server" (not "SLES")"name": "SUSE Linux Enterprise Server 15.7" (not "SLES 15.7")File names (rhel.json, sles.json) remain short — only the name fields inside must use full names. When creating new distro files or adding releases, always verify the display name is the full product name, not an abbreviation.