Wolfi OS Documentation

repository·main·Indexed 22 days ago

https://github.com/wolfi-dev/os

A lightweight, minimalist GNU software distribution designed for containerized and embedded environments. Built using melange and optimized for apko, Wolfi focuses on security and open-source licensing. Documentation covers package development with melange, the use of python-as-wrapper packages for sys.executable management, automated package updates via Release Monitor and GitHub backends, and CVE patching workflows.

Tokens
4.7K
Snippets
9
Records
30
Agent score
76%

What's inside Wolfi

  1. What is Wolfi

    main

    Wolfi is a lightweight GNU software distribution designed for minimalism and containerized environments. It is specifically optimized for workflows involving apko and is built using melange.

    Key characteristics:

    • Target Use Case: Containerized and embedded system workflows (not intended for general-purpose desktop use).
    • Security Focus: Aims to provide up-to-date security patches by using the latest package releases by default.
    • Licensing: Packages must use an open-source license (ideally FSF or OSI approved).
    • Package Repository: The APK package repository is located at https://packages.wolfi.dev/os.
    • Public Signing Key: Available at https://packages.wolfi.dev/os/wolfi-signing.rsa.pub.
  2. Compatibility warning: Mixing packages with other distributions

    main
    Wolfi uses the apk package manager, which is the same manager used by Alpine Linux. However, Wolfi packages and Alpine packages are NOT compatible. Mixing packages from different distributions can create security problems and is not supported.
  3. Choose an update backend for Melange packages

    main

    When configuring the update: section in a Melange package, you must choose a backend for the Wolfi Bot to monitor. The two available backends are:

    Release Monitor

    • Backend Key: update.release-monitor
    • Mechanism: Queries the release-monitoring.org REST API.
    • Frequency: Checked once per day via GitHub Actions.
    • Considerations: The versions returned may not always represent the absolute latest upstream version (e.g., for projects like kustomize or jenkins that have non-standard release patterns).

    GitHub

    • Backend Key: update.github
    • Mechanism: Uses GitHub's GraphQL API.
    • Frequency: Checked once per hour via a CRON job.
    • Considerations: Offers greater control and flexibility. It supports projects that do not use standard GitHub releases and handles complex release patterns better than Release Monitor. It is more efficient as a single GraphQL request can retrieve latest versions for multiple projects.
  4. Build requirements for PyYAML

    main
    When building the PyYAML package, an empty directory must be used as the build environment. This is required because certain files in the default repository cause conflicts during the build process. This requirement is a workaround for existing repository conflicts and may be removed if patches are implemented.
  5. Use python-as-wrapper packages to ensure correct sys.executable

    main

    In Wolfi, standard symlinks like /usr/bin/python3 pointing to a specific version (e.g., python3.13) can cause issues with sys.executable being 'sticky'. This leads to incorrect shbangs in scripts installed via pip and potential dependency mismatches.

    To solve this, use the python-as-wrapper packages. These provide shell script wrappers in /usr/bin/python3 and /usr/bin/python that use exec to invoke the specific version. This ensures that any Python code determining its own executable (arg0) finds the actual version (e.g., /usr/bin/python3.13) rather than the symlink name.

    Note: These packages are intended for use in package build systems to accommodate tools that invoke python3 or python, and are not intended for runtime production use.

  6. Use Dev Containers for Wolfi development

    main

    A devcontainer is provided for VSCode users, based on the sdk image. This allows for development in:

    • A local container
    • A remote container (via Docker remote protocols)
    • A remote GitHub Codespace

    This approach avoids configuring or tainting your local environment and is useful for leveraging high-performance remote machines for long builds.

  7. Caveats and known reproducibility issues in Wolfi

    main

    While Wolfi aims for full reproducibility via Melange and apko, several factors currently impact it:

    • Dependency Updates: Packages may not reproduce reliably if they are built with newer versions of dependencies. (Note: Melange 0.3 plans to address this with --reproduce-from [sbom]).
    • Signing Keys: The Wolfi signing key is private. Use abuild-reusesig to swap signatures on APKv2 packages.
    • Compiler Flags: Older packages used -D_FORTIFY_SOURCE=2, whereas current builds use -D_FORTIFY_SOURCE=3.
    • Architecture Optimizations: Recent moves to -march=x86-64-v2 and -mtune=broadwell break reproducibility for older packages that were not rebuilt with these new CFLAGS.
  8. Quickstart with the wolfi-base image

    main

    The fastest way to try out Wolfi is to run the wolfi-base image using Docker. This allows you to explore the environment and verify the OS identity.

    docker run -it cgr.dev/chainguard/wolfi-base
    
    # Inside the container, verify the OS:
    cat /etc/os-release
  9. Build a Wolfi package using Docker

    main

    To build a package, run the melange build command via the sdk Docker image.

    Important: You must use the --privileged flag because melange needs to spawn containers to isolate the build process.

    Required flags for a standard build:

    • --keyring-append:
      • Append your local public key (local-melange.rsa.pub).
      • Append the official Wolfi signing key (https://packages.wolfi.dev/os/wolfi-signing.rsa.pub).
    • --signing-key:
      • Provide your local private key (local-melange.rsa).
    • --repository-append:
      • Append the official Wolfi repository (https://packages.wolfi.dev/os).
      • Append your local packages directory (e.g., /work/packages).
    • --empty-workspace
    • --arch:
      • Specify the target architecture (e.g., x86_64).
    # build a package
    docker run --privileged -v "$PWD":/work --entrypoint=melange --workdir=/work ghcr.io/wolfi-dev/sdk build --keyring-append local-melange.rsa.pub --keyring-append https://packages.wolfi.dev/os/wolfi-signing.rsa.pub --signing-key local-melange.rsa --repository-append https://packages.wolfi.dev/os  --repository-append /work/packages --empty-workspace --arch x86_64 $package
  10. Reproduce the entire Wolfi OS

    main

    To verify the reproducibility of the entire Wolfi OS, you can build the OS twice using the same key. Alternatively, you can download the existing Wolfi package collection using gsutil.

    If you download the collection, you must use the abuild-reusesig tool to copy the original Wolfi package signatures to your own rebuilt packages to ensure signature verification does not fail during comparison.

    After obtaining two builds and normalizing the signatures, use a tool like diffoscope to compare the package directories and verify reproducibility.

  11. Reproduce an individual Wolfi package

    main

    To test the reproducibility of a specific package (e.g., execline), you can build the package twice in succession and compare the resulting APK files using sha256sum. Note that dependency packages will be sourced from the Wolfi repository during this process.

    Follow these steps:

    1. Build the package.
    2. Move the resulting packages directory to a temporary name (e.g., packages-1).
    3. Build the package again.
    4. Move the new packages directory to a second temporary name (e.g., packages-2).
    5. Use sha256sum with sed to compare the checksums of the files in both directories.
  12. Patch Go dependencies in Melange

    main

    For Go applications, vulnerabilities are often addressed by bumping dependencies using go get. This should be performed within a runs block in a Melange pipeline, ensuring it occurs after the source is fetched and before the build starts.

    Common pattern:

    go get golang.org/x/text@v0.3.8
    go mod tidy

    Notes:

    • Always run go mod tidy at the end of a series of go get commands.
    • If the application uses a vendor directory, use go mod vendor instead of go mod tidy.
    • If dependency conflicts arise, you may need to bump multiple dependencies or test the build locally outside of Melange.