/ubuntu-nix-sbom

SBOM in SPDX for Ubuntu, Nix, or both

Primary LanguageGoApache License 2.0Apache-2.0

Ubuntu-Nix SBOM Generator

A comprehensive SBOM (Software Bill of Materials) generator for systems running both Ubuntu and Nix packages. Generates SPDX 2.3 compliant JSON documents.

Features

  • Ubuntu SBOM Generation: Scans dpkg-installed packages on Ubuntu/Debian systems
  • Nix SBOM Generation: Uses sbomnix to analyze Nix derivations
  • Merged SBOM: Combines both Ubuntu and Nix packages into a single unified SBOM
  • SPDX 2.3 Compliant: Generates valid SPDX JSON documents
  • License Detection: Extracts license information from package metadata
  • Package URLs (purl): Includes purl references for both deb and nix packages

Prerequisites

  • Nix with flakes enabled
  • Ubuntu/Debian system (for Ubuntu SBOM generation)
  • Access to dpkg and package metadata

Installation

Clone the repository and enter the development shell:

git clone <repository-url>
cd ubuntu-nix-sbom
nix develop

Usage

The project provides several Nix flake apps for different use cases:

Combined SBOM (Ubuntu + Nix)

Generate a merged SBOM containing both Ubuntu and Nix packages:

nix run .#sbom-generator -- --nix-target /nix/store/xxx-system --output merged-sbom.json

Or use the alias:

nix run .#sbom-combined -- --nix-target /nix/store/xxx-system --output merged-sbom.json

Options:

  • --nix-target <path>: Required. Path to the Nix derivation to analyze
  • --output <file>: Output file path (default: merged-sbom.spdx.json)
  • --include-files: Include file checksums for Ubuntu packages (slower)
  • --progress: Show progress indicators (default: true)
  • --no-progress: Disable progress indicators

Example:

nix run .#sbom-generator -- \
  --nix-target /nix/var/nix/profiles/system \
  --output my-system-sbom.json \
  --include-files \
  --no-progress

Ubuntu-Only SBOM

Generate SBOM for Ubuntu/Debian packages only:

nix run .#sbom-ubuntu -- --output ubuntu-sbom.json

Options:

  • --output <file>: Output file path (default: ubuntu-sbom.spdx.json)
  • --include-files: Include file checksums (slower but more detailed)
  • --progress: Show progress indicators (default: true)
  • --no-progress: Disable progress indicators

Nix-Only SBOM

Generate SBOM for Nix packages only:

nix run .#sbom-nix -- /nix/store/xxx-derivation --output nix-sbom.json

Options:

  • --output <file>: Output file path (default: nix-sbom.spdx.json)

The derivation path is required as the first positional argument.

Validate SPDX

Validate an SBOM file against the SPDX 2.3 specification:

nix run .#validate-spdx -- my-sbom.spdx.json

This uses the official spdx-tools to verify compliance.

Available Flake Apps

App Description
sbom-generator Generate combined Ubuntu + Nix SBOM (default app)
sbom-combined Alias for sbom-generator
sbom-ubuntu Generate Ubuntu-only SBOM
sbom-nix Generate Nix-only SBOM using sbomnix
validate-spdx Validate SBOM against SPDX 2.3 specification

How It Works

Ubuntu SBOM Generation

  1. Queries dpkg for all installed packages
  2. Extracts metadata (version, architecture, maintainer, homepage)
  3. Reads license information from /usr/share/doc/<package>/copyright
  4. Optionally calculates SHA256 checksums of package files
  5. Generates SPDX 2.3 JSON with purl references (pkg:deb/ubuntu/...)

Nix SBOM Generation

  1. Uses sbomnix to analyze the specified derivation
  2. Extracts all dependencies and their metadata
  3. Generates SPDX 2.3 JSON with purl references (pkg:nix/...)

Merging Process

  1. Loads both Ubuntu and Nix SPDX documents
  2. Creates a new document with a single "SPDXRef-System" root package
  3. Renames package SPDXIDs to avoid conflicts:
    • Ubuntu packages: SPDXRef-Ubuntu-Package-*
    • Nix packages: SPDXRef-Nix-Package-*
  4. Preserves all package metadata and relationships
  5. Combines creator information from both sources
  6. Adds merger tool to the creator list

SPDX Document Structure

Merged SBOM

SPDXRef-DOCUMENT (describes) → SPDXRef-System
                                    ├── (contains) SPDXRef-Ubuntu-Package-1-bash
                                    ├── (contains) SPDXRef-Ubuntu-Package-2-curl
                                    ├── (contains) SPDXRef-Nix-Package-1-nixpkgs-...
                                    └── (contains) SPDXRef-Nix-Package-2-...

Package Identification

Duplicate packages (same software in both Ubuntu and Nix) are kept separate and identified by:

  • Different SPDXIDs (Ubuntu vs Nix prefix)
  • Different purl external references:
    • Ubuntu: pkg:deb/ubuntu/bash@5.1-6ubuntu1?arch=amd64
    • Nix: pkg:nix/nixpkgs/bash@5.1-...

Example Output

{
  "spdxVersion": "SPDX-2.3",
  "dataLicense": "CC0-1.0",
  "SPDXID": "SPDXRef-DOCUMENT",
  "name": "Ubuntu-Nix-System-SBOM-2025-11-05",
  "documentNamespace": "https://sbom.ubuntu-nix.system/...",
  "creationInfo": {
    "created": "2025-11-05T12:00:00Z",
    "creators": [
      "Tool: ubuntu-sbom-generator-1.0",
      "Tool: sbomnix-...",
      "Tool: ubuntu-nix-sbom-merger-1.0"
    ],
    "licenseListVersion": "3.20"
  },
  "packages": [
    {
      "SPDXID": "SPDXRef-System",
      "name": "Ubuntu-Nix-System",
      "downloadLocation": "NOASSERTION",
      "filesAnalyzed": false,
      "licenseConcluded": "NOASSERTION",
      "licenseDeclared": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "description": "Combined Ubuntu and Nix package system"
    },
    ...
  ],
  "relationships": [
    {
      "spdxElementId": "SPDXRef-DOCUMENT",
      "relatedSpdxElement": "SPDXRef-System",
      "relationshipType": "DESCRIBES"
    },
    ...
  ]
}

CI/CD

The project includes GitHub Actions workflows for automated testing and releases:

PR Checks

On every pull request to main:

  • Nix Flake Check: Runs nix flake check --all-systems to validate the flake
  • Formatting: Checks code formatting with nix fmt --fail-on-change
  • SPDX Validation:
    • Builds the Ubuntu SBOM generator
    • Generates a test SBOM
    • Validates the output against SPDX 2.3 specification using spdx-tools
    • Tests conversion to other SPDX formats (tag-value, XML, YAML)
    • Uploads test SBOM as artifact

Postgres SBOM Validation

On every pull request and push to main:

  • Dynamic Package Discovery: Uses nix flake show to discover all Supabase Postgres packages
  • Runtime Dependencies: Generates SBOMs with accurate runtime dependencies using sbomnix
  • SPDX Validation: Validates every generated SBOM against SPDX 2.3 specification
  • CPE Fixing: Automatically fixes invalid CPE references from upstream tools
  • Concurrency Control: Cancels previous runs when new commits are pushed

The workflow dynamically discovers and validates SBOMs for all packages except:

  • Extension packages (psql_*/exts/* - already included in psql_*/bin)
  • Documentation packages (require network access to build)

Automated Releases

On every merge to main:

  • Builds the ARM64 static binary on an ARM Linux runner
  • Tests the binary and validates SPDX output
  • Automatically increments the patch version (semver)
  • Creates a GitHub release with:
    • Changelog from commits since last release
    • ARM64 static binary as downloadable asset
    • SHA256 checksum file
    • Installation and verification instructions
    • Binary size

The release workflow uses semantic versioning (e.g., v1.2.3) and automatically tags releases.

Static Binary (Ubuntu-Only, No Nix Required)

For Ubuntu/Debian systems without Nix, a static binary is available that generates Ubuntu-only SBOMs.

Using the Static Binary

The ubuntu-sbom binary is a standalone executable with no dependencies:

# Download from GitHub release
curl -LO https://github.com/YOUR_ORG/ubuntu-nix-sbom/releases/latest/download/ubuntu-sbom-arm64
chmod +x ubuntu-sbom-arm64

# Generate Ubuntu SBOM
./ubuntu-sbom-arm64 --output my-system.spdx.json

Options:

  • --output <file>: Output file path (default: ubuntu-sbom.spdx.json)
  • --include-files: Include SHA256 checksums of all package files (slower)
  • --progress: Show progress indicators (default: true)
  • --no-progress: Disable progress indicators

Example with all options:

./ubuntu-sbom-arm64 \
  --output detailed-sbom.json \
  --include-files \
  --no-progress

This binary only scans dpkg-installed packages and does not require Nix.

Building Static Binaries for Release

The flake includes static binary builds that can be distributed to Ubuntu users:

Build ARM64 static binary:

nix build .#ubuntu-sbom-static-arm64 -o result-arm64

The binary will be at result-arm64/bin/ubuntu-sbom (~2.4MB, statically linked).

Build for current system:

nix build .#ubuntu-sbom-static -o result-static

Creating a GitHub Release

# Build the binary
nix build .#ubuntu-sbom-static-arm64 -o result-arm64

# Create a GitHub release
gh release create v1.0.0 \
  result-arm64/bin/ubuntu-sbom#ubuntu-sbom-arm64 \
  --title "v1.0.0" \
  --notes "Ubuntu SBOM Generator v1.0.0"

Users can then download and run directly on Ubuntu ARM64 systems:

# Download from GitHub release (use -L to follow redirects)
curl -LO https://github.com/YOUR_ORG/ubuntu-nix-sbom/releases/download/v1.0.0/ubuntu-sbom-arm64
chmod +x ubuntu-sbom-arm64

# Run without Nix
./ubuntu-sbom-arm64 --output my-sbom.json

Validating SPDX Output

The project uses the official spdx-tools to validate SPDX 2.3 compliance.

Install SPDX validation tools:

pip install spdx-tools

Validate an SBOM:

# Generate an SBOM
nix run .#sbom-ubuntu -- --output my-sbom.spdx.json

# Validate it against SPDX 2.3 specification
pyspdxtools -i my-sbom.spdx.json --validate

Convert to other SPDX formats:

# Convert to SPDX tag-value format
pyspdxtools -i my-sbom.spdx.json -o my-sbom.spdx --output-format tag-value

# Convert to SPDX XML format
pyspdxtools -i my-sbom.spdx.json -o my-sbom.spdx.xml --output-format xml

# Convert to SPDX YAML format
pyspdxtools -i my-sbom.spdx.json -o my-sbom.spdx.yaml --output-format yaml

Validation in CI/CD

Both the PR check and release workflows automatically validate SPDX output:

  • PR workflow: Validates test SBOMs and uploads them as artifacts
  • Release workflow: Validates SPDX output before creating releases

Development

Enter the development shell:

nix develop

This provides:

  • Go toolchain
  • gopls (Go language server)
  • sbomnix
  • SPDX validation tools (spdx-tools)
  • Formatting tools (nixfmt, shellcheck, shfmt, gofmt)
  • Pre-commit hooks (automatically installed)

Build the Go binaries manually:

# Build the Ubuntu-only static binary
go build -o ubuntu-sbom main.go

# Build the full sbom tool with all subcommands
go build -o sbom ./cmd/sbom

Code Formatting

The project uses treefmt to format code automatically. Formatters are configured for:

  • Nix files: nixfmt-rfc-style
  • Shell scripts: shellcheck and shfmt
  • Go code: gofmt
  • Dead code removal: deadnix

Format all files:

nix fmt

Check formatting without modifying files:

nix flake check

Pre-commit Hooks

Pre-commit hooks are automatically installed when entering the dev shell. They will:

  • Run treefmt on all staged files before each commit
  • Ensure code is properly formatted

To manually run the pre-commit checks:

nix flake check

The hooks will automatically format your code when you commit changes.

License

Apache-2.0

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.

The Apache-2.0 license is compatible with sbomnix (also Apache-2.0), which this project integrates with for Nix SBOM generation.

Contributing

Contributions welcome! Please open issues or pull requests.

References