Core Concepts
Choose a mode
| Need | Plain | Managed |
|---|---|---|
| Build indexes from a package directory | sow create DIR |
Import packages with sow add |
| Keep configuration and package membership | Directory contents are the state | sow.yml and private SQLite databases |
| Organize packages | One flat directory; RPM and DEB can coexist | Named Dists; one format per Dist |
| Publish architecture views | No | Yes |
| Apply filters and version limits | Pigsty conventions with --pigsty |
Configurable per Dist |
| Sign RPM packages | Yes | Yes |
| Sign repository metadata | Sign separately | Configure keys in sow.yml |
| Track generations and publication | Manage these outside SOW | Built in |
Use Plain when the directory already contains the packages you want to publish. Use Managed when SOW should track membership and maintain the repository over time.
Workspace, Repository, and Dist
A workspace holds configuration and private state for one or more repositories.
A Repository owns a package pool, Dists, build history, and publication targets. Serve its complete pool/ and dists/ tree. Keep sow.yml and .sow/ outside the HTTP document root.
A Dist selects packages of one format. For example, el9 can contain RPMs and bookworm can contain DEBs. You choose the names; SOW does not check whether a package is compatible with the operating system named by its Dist.
An architecture view contains metadata for one architecture. SOW includes neutral RPM noarch and DEB all packages in each applicable view.
Store each package once
SOW identifies a package object by the SHA-256 of the complete package file. It reads the package name, version, and architecture from package metadata.
Within a Repository, each accepted package has one path under pool/. Multiple Dists can refer to that path. Separate repositories have separate pools.
RPM metadata uses relative paths back to the pool. APT Packages entries use paths relative to the Repository root. Keep the complete Repository tree together when you serve or copy it.
Some mirror tools, including default dnf reposync, reject the parent-relative RPM paths. Use sow export rpm-leaf to create a standalone RPM repository for those tools.
Desired membership and built generations
Desired membership is the package set selected for each Dist. A Generation identifies a completed build and its file manifest. Built Generation is the current completed build. Package files stay in the shared pool; each build does not create another copy.
add and rm normally update membership and build the affected Dists in one command. With --skip, they update membership only. Run sow build after a batch of skipped changes, or after changing build or signing configuration.
| Command | Use |
|---|---|
sow status |
Read the current state and ready_to_copy value |
sow check |
Check package files, indexes, signatures, and recorded state without changing them |
sow changes [BASE_GENERATION] |
List file changes from a recorded generation to the current build |
sow publish TARGET |
Check and publish the current build to a configured target |
Understand repository state
| State | Meaning | Next action |
|---|---|---|
clean |
Membership and configuration match the built output | Ready for check or publication |
dirty |
Membership or configuration needs a build | Run build, then check |
recovering |
An interrupted operation needs recovery | Follow the error and recovery steps |
error |
Stored state or files conflict | Inspect the reported error and operation log |
Use sow log to inspect failed or interrupted operations.