메뉴
HN
Hacker News • 2일 전

tine: 부팅 가능한 이미지를 만드는 새 빌드 시스템

IMP
6/10
핵심 요약

Daan De Meyer와 Martin Pitt가 Buck2 기반의 새로운 오픈소스 빌드 시스템 'tine'을 공개했습니다. 암호학적으로 검증 가능한 무결성을 가진 운영체제를 만들기 위해 밀봉형(hermetic) 재현 가능 빌드, 완전한 입력 고정(pinning), 저렴한 전체 재빌드 등을 요구사항으로 설계되었습니다. 기존 도구인 mkosi와 Open Build Service를 검토했으나 각각 이미지 중심 프레임워크라는 한계로 자체 시스템을 만들게 되었다는 내용입니다.

번역된 본문

2026년 9월 24일, 13분 분량 읽기

공기 중에서부터 부팅 가능한 이미지까지: tine 빌드 시스템

작성: Daan De Meyer, Martin Pitt

목차

이 글은 최근 몇 달간 진행한 오픈소스 작업을 다루는 시리즈의 일부입니다. 오늘 우리는 새로운 Buck2 기반 빌드 시스템인 tine을 소개하고 공개합니다.

우리의 요구사항

암호학적으로 검증 가능한 무결성을 지닌 운영체제를 만들려면 그러한 속성을 갖춘 빌드 시스템에서 출발해야 합니다. 동시에 우리는 더 넓은 오픈소스 커뮤니티의 일원으로서 기여하고 기존 작업을 최대한 재사용하고자 합니다. 또한 빠른 사이클의 효율적인 개발을 지향합니다. 이는 대략 다음과 같은 빌드 시스템 요구사항으로 정리됩니다:

최소한의 호스트 요구사항. 자기 완결적(self-contained)이어야 하고 외부 의존성을 최소화하여 어떤 환경에서도 실행할 수 있어야 합니다.

입력에 대한 완전한 제어. 제품에 들어가는 모든 소프트웨어를 고정(pinning)할 수 있어야 합니다. 상류 배포판(Fedora, CentOS, Arch, Debian 등)을 선택할 수 있고 가능한 한 기존 패키지를 재사용하면서도, CVE에 신속히 대응하고 필요할 때 상류 패키징 결정에서 (일시적 또는 영구적으로) 벗어나기 쉬워야 합니다.

통합된 패키지 처리 기능. 가져온 패키지의 임포트, 업데이트, 병합을 위한 도구를 제공해야 합니다.

저렴한 전체 재빌드(world rebuild). 예를 들어 gcc 버전이 올라간 후 필요할 때 전체를 재빌드할 수 있어야 합니다.

밀봉형(hermetic) 재현 가능 빌드. 모든 컴포넌트와 이미지 빌드는 밀봉된 환경에서 실행되어야 하고 비트 단위로 동일하게 재현 가능한 결과물을 생성해야 합니다.

네이티브 이미지 빌드. 부팅 가능한 운영체제 이미지와 systemd sysext 이미지를 네이티브로 동시에 빌드할 수 있어야 합니다.

모노레포 기반 반복 개발. 빠른 종단간(end-to-end) 반복 작업을 위해 운영체제를 단일 최상위 모노레포로 유지할 수 있어야 합니다. 가져온 rpm이나 Go 또는 Rust 컴포넌트의 변경이 중간 커밋이나 푸시, 복잡한 버전·의존성 선언 없이도 전체 이미지 세트 전반에서 즉시 빌드 및 테스트 가능해야 합니다.

일급 커스텀 컴포넌트. 고정된 외부 저장소(예: kubernetes, varlink-http-bridge)의 Go와 Rust 프로젝트를 네이티브로 효율적으로 빌드할 수 있어야 합니다.

스캐너 호환성. 빌드된 이미지는 syft/grype 또는 trivy 같은 표준 SBOM 도구와 보안 스캐너에서 동작해야 합니다.

캐싱. 빌드가 변경되지 않은 컴포넌트를 로컬 및/또는 글로벌 캐시에서 가져올 수 있어야 합니다. 모든 것을 처음부터 빌드하면 몇 시간이 걸릴 수 있는데, 개발자는 보통 단일 컴포넌트만 작업합니다.

기존 도구

자체 빌드 도구를 만들기 전에 여러 옵션을 평가했습니다.

mkosi

우리 팀에 mkosi의 창시자이자 메인테이너가 포함되어 있기 때문에 자연스럽게 첫 번째 평가 대상이었습니다. 하지만 근본적인 한계가 있다는 결론에 빠르게 도달했습니다. 상류 패키지 기반으로 개별 이미지를 빌드하는 데는 훌륭하지만, 느슨하게 연관된 여러 이미지를 빌드하거나 이미지를 구성하는 아티팩트에 대한 더 많은 제어가 필요할 때는 제약이 됩니다. 여러 이미지 빌드는 "메인" 이미지의 일부로 배포될 이미지로 제한됩니다. 우리는 이미지뿐 아니라 다양한 종류의 아티팩트를 균일하고 견고하게 빌드할 필요가 있으며, 따라서 빌드는 범용적이고 유연한 도구로 오케스트레이션되어야 합니다. 메인 빌드 파일은 "cargo 크레이트 컴파일" 또는 "UKI 빌드" 같은 라이브러리 함수를 호출하는 언어여야 합니다. mkosi는 정반대로 프레임워크입니다. 이미지 빌드 방법을 알고 있으며, 다른 종류의 빌드에는 자유 형식의 불투명한 훅만 제공합니다. 그래서 이미지 이상을 빌드하고자 하면 좋지 않은 경험이 됩니다.

Open Build Service

Open Build Service(OBS)는 주로 SUSE와 openSUSE 프로젝트에서 패키지부터 ISO 및 기타 다양한 이미지 형식에 이르는 모든 아티팩트를 생산하는 데 사용되는 강력한 완전 통합 빌드 시스템입니다. 강력한 의존성 추적을 갖추고 있고…(원문 누락)

원문 보기
원문 보기 (영어)
Sep 24, 2026 13 min read From Thin Air to Bootable Images: The tine Build System By Daan De Meyer and Martin Pitt Table of contents This post is part of a series covering some of the open source work we have been doing in recent months. Today we introduce and publish tine , our new Buck2-based build system. Our Requirements Building an operating system with cryptographically verifiable integrity has to start with a build system with these very properties. At the same time, we are part of the greater open source community and want both to contribute and re-use as much existing work as possible. We also aim for efficient development with fast turnaround. This roughly translates into the following requirements for our build system: Minimal host requirements. It must be self-contained and must minimize external dependencies, so that it can be run in any environment. Full control over inputs. It must allow pinning every piece of software that goes into a product. It must support a choice of upstream distributions (Fedora, CentOS, Arch, Debian, etc.) and reuse existing packages where possible, while still making it easy to react quickly to CVEs and to diverge (either temporarily or permanently) from upstream packaging decisions when necessary. Integrated package machinery. It must provide tooling for importing, updating, and merging imported packages. Cheap world rebuilds. It must be able to rebuild the world on demand, e.g. after a gcc bump. Hermetic, reproducible builds. All component and image builds must run in a hermetic environment and produce bitwise reproducible output. Native image builds. It must be able to build bootable operating system images and systemd sysext images natively and concurrently. Monorepo-based iteration. It must support maintaining the operating system in a single top-level monorepo for fast end-to-end iteration. A change to an imported rpm or to a Go or Rust component must be immediately buildable and testable across the full set of images, without intermediate commits or pushes and without elaborate version or dependency declarations. First-class custom components. It must natively and efficiently build Go and Rust projects from pinned external repositories, for example kubernetes or varlink-http-bridge . Scanner compatibility. Built images must work with standard SBOM tooling and security scanners such as syft / grype or trivy . Caching. Builds must be able to retrieve unchanged components from a local and/or global cache. Building everything from scratch can take hours, and a developer is usually only working on a single component. Existing Tools Before building our own build tool, we evaluated several options. mkosi Given our team includes the creator and maintainer of mkosi , it was a natural first candidate to evaluate. But we quickly came to the conclusion that it has some fundamental shortcomings. It’s great at building individual images based on upstream packages, but becomes restrictive when building several weakly related images or if you need more control over the artifacts that make up an image. Building multiple images is limited to images that are intended to be shipped as part of the “main” image. We need to build many different kinds of artifacts in a uniform and robust way, not just images. Hence the build needs to be orchestrated by a generic and flexible tool. The main build file should be a language calling into library functions like “compile a cargo crate” or “build a UKI ”. mkosi is the opposite, it’s a framework : It knows how to build images, and only gives you free-form opaque hooks for the other kinds of builds. That leads to a bad experience when you want to build more than just images. Open Build Service The Open Build Service (OBS) is a powerful fully-integrated build system that is primarily used by SUSE and the openSUSE project to produce all of their artifacts, anything from packages to ISOs, and many other image formats. It has strong dependency tracking and supports a dizzying array of distributions. However, it’s also the antithesis of “minimal host requirements”. The server side of it is required, central, and non-trivial to self-host. It’s also not a generic build system, meaning any new artifact types would either have to be modelled as packages or require heavy patches to OBS. We concluded that this lack of flexibility combined with its overall architecture would make it difficult for OBS to meet our requirements. BuildStream Apache BuildStream describes the operating system image as a graph of YAML "elements", each with its own sources, dependencies and build commands. BuildStream builds each one in a bubblewrap sandbox and caches the result under a hash of everything that went into it, similar to Buck2. It is mature and used to build freedesktop-sdk , GNOME OS , and WebKitGTK . Our concerns with BuildStream are mostly around bootstrapping and extensibility. BuildStream is a Python application with compiled extensions and other dependencies. It relies on a separate set of helper programs, plus sandboxing tools from the host. Each of those can be pinned, but through different mechanisms, and even then the result still depends on the host's Python. In practice you run it from a pinned container image instead, but then you’re still dependent on an entire container runtime you don’t control. BuildStream’s YAML is a plain data format, and is extended with Python plugins. YAML has no functions, so over time you end up copy-pasting across the project. Ultimately we decided to go for a tool with a better bootstrapping and pinning story as well as a more flexible language. Antlir Antlir is Meta's OS image builder, built on top of the Buck2 build system engine. Buck2 is Meta's open source build system with emphasis on correctness, flexibility, and caching as much as possible. Antlir implements various rules for building images with Buck2. As Antlir is a high-level tool focused on Meta’s internal repository, it is naturally very opinionated and designed for Meta’s internal use cases. For example, it requires btrfs and is strongly focused on a single monorepo. While we decided against using Antlir itself, its underlying engine, Buck2, turned out to be a good fit, and we ended up choosing it as the foundation for our own build system. Our Build System: tine In essence, tine is a set of opinionated Buck2 rules to build rpm, Rust crate and Go module components, UKIs , and images; it can sign images either with a hardware key through PKCS#11 or a locally generated key. The intent is to combine the best ideas from Antlir and mkosi into a single tool. tine has only three requirements on its build host: git, python3 (just for its own bootstrapping, not for production builds) and user namespaces. From there, it bootstraps everything it needs from pinned declarations to get a reproducible and independent build environment. That can be a distribution as old or modern as you need. An important tine concept is the “ box ”, which is a declared and pinned down environment to run a build task. Think containers or distrobox , but declared natively in Buck2’s language, and using Buck2’s caching and rebuild rules, so they build quickly and naturally, stay reproducible, and need no further dependencies to run. tine itself defines boxes for running rpmbuild, go, or cargo, or a bigger multi-purpose one called fedora.rawhide.box which contains e.g. systemd-ukify for building images and QEMU for running virtual machines. Your own project can define its own boxes. tine’s Engine: Buck2 To better understand this post and the examples, here is a one-minute Buck2 primer for those familiar with Make or Meson : Build file: A BUCK file is the directory's Makefile equivalent. It's written in a Python dialect called Starlark , and declares all targets that you can build. Cell: A named build graph root; these roughly follow the boundaries of git repositories: // is your own top-level project (the OS you